You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@freemarker.apache.org by Daniel Dekany <dd...@freemail.hu> on 2016/11/01 18:51:46 UTC

Re: Call "assign" directive in a user-defined java directive

Hi,

It's doable (see later), but first I would like point out that doing
assignments inside custom directives is very often a disadvantageous
approach. If you need to produce a value, then use a method
(function), which if you are implementing it in Java, will be a
TemplateMethodModelEx implementation. Then you can do this:

  <#assign feed = readFeed("http://www.spiegel.de/einestages/index.rss")>

and also you can do <#local feed = readFeed(...)>, <#list
readFeed(...).entries as entry>, etc., because readFeed(...) is just
an expression that can be put anywhere. (The places where directives
can be used are much more limited, and they aren't meant to produce
values.)

If you still want to do an assignment, then in the freemarker.core.Environment
object (which you get as argument if it's a TemplateDirectiveModel)
there's a setVariable(String name, TemplateModel model) method that
does what #assign do.


Monday, October 31, 2016, 9:13:18 PM, Ingo Mahnke wrote:

> Hallo!
>
> Maybe someone can help me:
>
> I wrote a user-defined directive in java, called "readFeed".
>
> In the template I write the following:
>
> <@readFeed name="feed"
> source="http://www.spiegel.de/einestages/index.rss" />
>
> My whish is to use the word "feed" as a normal variable
> (Type:SyndFeed) and I want to be able to write something like this:
>
> <#list entry as feed.entries>
>   .........
> </#list> 
>
> The question:
> How can I call the "assign" directive within my java code of my
> "ReadFeed" directive to create a freemarker variable of name "feed"?
>
> Thank you very much
> Ingo
>
>
>
>  
>

-- 
Thanks,
 Daniel Dekany


Re: Aw: Re: Call "assign" directive in a user-defined java directive

Posted by Daniel Dekany <dd...@freemail.hu>.
I recommend you to use Environment.getObjectWrapper() instead of
creating a new BeansWrapper, if you can. Thus when someone configures
the ObjectWrapper in the Configuration, that will have an effect
consistently everywhere. (Surely then you will need to do an unsafe
cast to BeansWrapper, but you can say that a configuration with a such
ObjectWrapper is required for this directive/method, and pretty much
everyone uses a ObjectWrapper that extends BeansWrapper anyway.)

In case you really need to have you own ObjectWrapper inside readFeed,
at least use BeansWrapperFactory, so the introspection caches will be
reused. Or even better, you could just store the BeansWrapper instance
inside the TemplateDirectiveModel or TempalteMetholdModelEx as a final
field, so it's only created once ever. (I also wonder why's that a
BeansWrapper instead of a DefaultObjectWrapper.)

Tuesday, November 1, 2016, 8:19:26 PM, Ingo Mahnke wrote:

> Hallo and thank you!!
>
> Yesterday I found the "setVariable"-Method in the Environment-Class
> and solved my problem in this way:
>
> SyndFeed feed = input.build(new XmlReader(httpCon));
> BeansWrapper beanWrapper = new
> BeansWrapper(Configuration.VERSION_2_3_25);
> BeanWrapper.setExposeFields(true);
> BeanModel feedObj = new BeanModel(feed, beanWrapper);
> env.setVariable(name, feedObj);
>
>
> It works(!), but I will change it to your idea:
>
> <#assign feed =
> readFeed("http://www.spiegel.de/einestages/index.rss")>
>
> This looks clearer. Thank you!
>
>
>
> Currenty I have the following problem and I am afraid that freemarker will
> currently not support this:
>
> I have one function called "a" and I have one custome derective called "b".
> "a" has one paramter called "name" and "b" has a string parameter.
>
> Now the following seems not to be possible:
>
> <@a data="feed" markupProperty="${b("test")}"/>
>
> The ferrmarker engine gives me a parse error and said "(" is not closed.
>
> Is something like this possible or made i a mistake?

It's because the second quotation mark terminates the string literal,
so you end up with a "${b(". You could use single quotation mark for
some of the intended literals to fix that, but you shouldn't use ${}
there at all. Then it's like this:

  <@a data="feed" markupProperty=b("test") />

Furthermore if "feed" is a variable name, then remove the quotation
marks there too, or else it will be just a string, and won't be
resolved:

  <@a data=feed markupProperty=b("test") />

Quotation mark means string for FreeMarker, just like in Java. Do not
quote other kind of expressions.

> THANK YOU
> Ingo
>
>
>
>
>
>  
>  
>
>
>
>
>
>
>
>> Gesendet: Dienstag, 01. November 2016 um 19:51 Uhr
>> Von: "Daniel Dekany" <dd...@freemail.hu>
>> An: "Ingo Mahnke" <in...@quvion.org>
>> Cc: dev@freemarker.incubator.apache.org
>> Betreff: Re: Call "assign" directive in a user-defined java directive
>>
>> Hi,
>> 
>> It's doable (see later), but first I would like point out that doing
>> assignments inside custom directives is very often a disadvantageous
>> approach. If you need to produce a value, then use a method
>> (function), which if you are implementing it in Java, will be a
>> TemplateMethodModelEx implementation. Then you can do this:
>> 
>>   <#assign feed = readFeed("http://www.spiegel.de/einestages/index.rss")>
>> 
>> and also you can do <#local feed = readFeed(...)>, <#list
>> readFeed(...).entries as entry>, etc., because readFeed(...) is just
>> an expression that can be put anywhere. (The places where directives
>> can be used are much more limited, and they aren't meant to produce
>> values.)
>> 
>> If you still want to do an assignment, then in the freemarker.core.Environment
>> object (which you get as argument if it's a TemplateDirectiveModel)
>> there's a setVariable(String name, TemplateModel model) method that
>> does what #assign do.
>> 
>> 
>> Monday, October 31, 2016, 9:13:18 PM, Ingo Mahnke wrote:
>> 
>> > Hallo!
>> >
>> > Maybe someone can help me:
>> >
>> > I wrote a user-defined directive in java, called "readFeed".
>> >
>> > In the template I write the following:
>> >
>> > <@readFeed name="feed"
>> > source="http://www.spiegel.de/einestages/index.rss" />
>> >
>> > My whish is to use the word "feed" as a normal variable
>> > (Type:SyndFeed) and I want to be able to write something like this:
>> >
>> > <#list entry as feed.entries>
>> >   .........
>> > </#list> 
>> >
>> > The question:
>> > How can I call the "assign" directive within my java code of my
>> > "ReadFeed" directive to create a freemarker variable of name "feed"?
>> >
>> > Thank you very much
>> > Ingo
>> >
>> >
>> >
>> >  
>> >
>> 
>> -- 
>> Thanks,
>>  Daniel Dekany
>> 
>> 
>

-- 
Thanks,
 Daniel Dekany


Aw: Re: Call "assign" directive in a user-defined java directive

Posted by Ingo Mahnke <in...@quvion.org>.
Hallo and thank you!!

Yesterday I found the "setVariable"-Method in the Environment-Class and solved my problem in this way:

SyndFeed feed = input.build(new XmlReader(httpCon));
BeansWrapper beanWrapper = new BeansWrapper(Configuration.VERSION_2_3_25);
BeanWrapper.setExposeFields(true);
BeanModel feedObj = new BeanModel(feed, beanWrapper);
env.setVariable(name, feedObj);


It works(!), but I will change it to your idea:

<#assign feed = readFeed("http://www.spiegel.de/einestages/index.rss")>

This looks clearer. Thank you!



Currenty I have the following problem and I am afraid that freemarker will 
currently not support this:

I have one function called "a" and I have one custome derective called "b".
"a" has one paramter called "name" and "b" has a string parameter.

Now the following seems not to be possible:

<@a data="feed" markupProperty="${b("test")}"/>

The ferrmarker engine gives me a parse error and said "(" is not closed.

Is something like this possible or made i a mistake?

THANK YOU
Ingo





 
 







> Gesendet: Dienstag, 01. November 2016 um 19:51 Uhr
> Von: "Daniel Dekany" <dd...@freemail.hu>
> An: "Ingo Mahnke" <in...@quvion.org>
> Cc: dev@freemarker.incubator.apache.org
> Betreff: Re: Call "assign" directive in a user-defined java directive
>
> Hi,
> 
> It's doable (see later), but first I would like point out that doing
> assignments inside custom directives is very often a disadvantageous
> approach. If you need to produce a value, then use a method
> (function), which if you are implementing it in Java, will be a
> TemplateMethodModelEx implementation. Then you can do this:
> 
>   <#assign feed = readFeed("http://www.spiegel.de/einestages/index.rss")>
> 
> and also you can do <#local feed = readFeed(...)>, <#list
> readFeed(...).entries as entry>, etc., because readFeed(...) is just
> an expression that can be put anywhere. (The places where directives
> can be used are much more limited, and they aren't meant to produce
> values.)
> 
> If you still want to do an assignment, then in the freemarker.core.Environment
> object (which you get as argument if it's a TemplateDirectiveModel)
> there's a setVariable(String name, TemplateModel model) method that
> does what #assign do.
> 
> 
> Monday, October 31, 2016, 9:13:18 PM, Ingo Mahnke wrote:
> 
> > Hallo!
> >
> > Maybe someone can help me:
> >
> > I wrote a user-defined directive in java, called "readFeed".
> >
> > In the template I write the following:
> >
> > <@readFeed name="feed"
> > source="http://www.spiegel.de/einestages/index.rss" />
> >
> > My whish is to use the word "feed" as a normal variable
> > (Type:SyndFeed) and I want to be able to write something like this:
> >
> > <#list entry as feed.entries>
> >   .........
> > </#list> 
> >
> > The question:
> > How can I call the "assign" directive within my java code of my
> > "ReadFeed" directive to create a freemarker variable of name "feed"?
> >
> > Thank you very much
> > Ingo
> >
> >
> >
> >  
> >
> 
> -- 
> Thanks,
>  Daniel Dekany
> 
> 

Re: Call "assign" directive in a user-defined java directive

Posted by br...@me.com.
That's not the best way to do it. 

What Ingo is asking is basically what loop variables are for. 

You can do:

<@readFeed source="ht‎...">
Here ${entry} contains the current ‎feed entry...
</...@readFeed>

‎The usual usage would have the body repeated for each entry in the feed (like a #list tag), but you can also make a "feed" variable available in the body and not repeat it. In that case you should use #list explicitly to go through the entries of the feed. 

-- Denis.
  Original Message  
From: Daniel Dekany
Sent: Tuesday, 1 November 2016 18:52
To: Ingo Mahnke
Reply To: dev@freemarker.incubator.apache.org
Cc: dev@freemarker.incubator.apache.org
Subject: Re: Call "assign" directive in a user-defined java directive

Hi,

It's doable (see later), but first I would like point out that doing
assignments inside custom directives is very often a disadvantageous
approach. If you need to produce a value, then use a method
(function), which if you are implementing it in Java, will be a
TemplateMethodModelEx implementation. Then you can do this:

<#assign feed = readFeed("http://www.spiegel.de/einestages/index.rss")>

and also you can do <#local feed = readFeed(...)>, <#list
readFeed(...).entries as entry>, etc., because readFeed(...) is just
an expression that can be put anywhere. (The places where directives
can be used are much more limited, and they aren't meant to produce
values.)

If you still want to do an assignment, then in the freemarker.core.Environment
object (which you get as argument if it's a TemplateDirectiveModel)
there's a setVariable(String name, TemplateModel model) method that
does what #assign do.


Monday, October 31, 2016, 9:13:18 PM, Ingo Mahnke wrote:

> Hallo!
>
> Maybe someone can help me:
>
> I wrote a user-defined directive in java, called "readFeed".
>
> In the template I write the following:
>
> <@readFeed name="feed"
> source="http://www.spiegel.de/einestages/index.rss" />
>
> My whish is to use the word "feed" as a normal variable
> (Type:SyndFeed) and I want to be able to write something like this:
>
> <#list entry as feed.entries>
> .........
> </#list> 
>
> The question:
> How can I call the "assign" directive within my java code of my
> "ReadFeed" directive to create a freemarker variable of name "feed"?
>
> Thank you very much
> Ingo
>
>
>
> 
>

-- 
Thanks,
Daniel Dekany