Re: Sharing constants in .java and .ftl files
Daniel Dekany <[email protected]>
| Newsgroups | gmane.comp.web.freemarker.user |
|---|---|
| Message-ID | <[email protected]> |
Sunday, November 16, 2008, 9:18:58 PM, Luther Baker wrote:
> I'd like to store something in the root hashmap and retrieve it in an
> FTL file.
>
> I'd like to avoid 'strings' as keys everywhere so I'd like to abstract
> that out - into a Constants class or something.
>
>
> CURRENT STYLE: notice the "projects" key in the class file ... and
> rigid reference (not a string) in the FTL file.
>
> .class:
> root.put("projects", projectList);
>
> .ftl
> <#list projects[] as p>
> <li>${p.name}</li>
> </#list>
>
>
> NEW STYLE: I'd like to do this - but I don't know what to do at
> the ???? below.
>
> Constants.java
> public class Constants
> {
> public static final String PROJECTS = "projects";
> }
>
> .class:
> root.put(Constants.PROJECTS, projectList);
>
> .ftl
> <#list ?????[] as p>
> <li>${p.name}</li>
> </#list>
Er... but the java coded is equivalent with the previous one... so the
FTL should be <#list projects[] as p> again. Are you sure this is what
you wanted to ask?
> Furthermore, I'd like this Constants class available globally. Maybe
> I can assign it in an FTL I load at the beginning ... but since it
> is not a TemplateMethodModel or TemplateDirectiveModel, I'm not sure
> how to put it into the root scope permanently as a Java object. I
> guess - core this is the question - can I put POJOs into the root
> namespace ... and if so, how do I do that? Most of what I'm reading
> is more specific to the above named interfaces and their subsequent
> predefined methods.
You can put POJO-s into the data-model root, furthermore that's usual
way of doing that. Like, looking at
http://freemarker.org/docs/pgui_quickstart_all.html you see that there
are no TemplateXxxModel-s around at all, just POJO-s, yet we have
built a full data-model. Surely in that basic example we just add
String-s and simple stuff like that to the data-model, but you could
also add other kind of objects as well.
Regarding adding data-model entries globally, you can use
freemarker.core.Configurable.Configuration.setSharedVariable for that.
As you can is in the API, you can add both TemplateModel-s or POJO-s.
Or, you could use a custom-class TemplateHashModelEx as the data-model
root, which would act as an usual SimpleHash, only it would
automatically expose the static fields of a given class... BTW that's
one reason why one sometimes wants to deal with TemplateModel-s as
opposed to POJO-s. It gives you extra power, but if you don't need
that, just use POJO-s, like a java.util.Map as the data-model root.
> One the POJO is in the namespace, can I invoke arbitrary methods ...
Yes. Depends on the settings of the ObjectWrapper anyway, but be
default yes. See:
http://freemarker.org/docs/api/freemarker/ext/beans/BeansWrapper.html#setExposureLevel(int).
Although the default wrapper is
freemarker.template.DefaultObjectWrapper, not
freemarker.ext.beans.BeansWrapper, the only difference is that
DefaultObjectWrapper wraps String-s, Number-s, Date-s, List-s and
Map-s and few such basic classes specially, so you will not access
their methods (because you should use the FTL built-ins, like
myList?size, instead of myList.size()), but you will still access the
methods of other classes. (Oh, and it also treats org.w3c.dom.Node
specially, so you can process XML easily.)
> or look at arbitrary fields ....
Yes, but not be default. See:
http://freemarker.org/docs/api/freemarker/ext/beans/BeansWrapper.html#setExposeFields(boolean)
> and then finally, what syntax allows a string field serve as the
> 'list' parameter of the <#list macro ...
Such things are solved on the wrapping level, not on the FTL level.
FTL, the template language, only deals with TemplateModel-s; that's
what the native type-system of the template language is built from.
But behind the scenes there is (are) the ObjectWrapper(-s) that
translate POJO-s to TemplateModel-s. So if you have something that's a
String, and you want to expose that to the template as a sequence,
then the ObjectWrapper must translate (or as we call it: wrap) the
string into a TemplateSequenceModel or TemplateCollectionModel.
Actually, ObjectWrappers are not that much behind the scenes, as the
related API-s are public, and it's not rare that users fiddle with
them.
> Thanks for all your time parsing this :) Hope it is an easy answer.
>
> -Luther
--
Best regards,
Daniel Dekany
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/