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 2017/01/24 22:47:52 UTC

Re: Pluggable template retrival/caching logic (Was: Template Loader Implementation that loads from a database (DataSource))

Tuesday, January 24, 2017, 9:27:37 PM, David E Jones wrote:

> On Jan 24 2017, at 10:25 am, Daniel Dekany <dd...@freemail.hu> wrote:
>
>> Tuesday, January 24, 2017, 6:48:16 PM, David E Jones wrote:
>
>>
>
>> > but all other Configuration.getTemplate() methods call this method  
>
>>
>
>> > so it is an easy way to override all Template loading (assuming you  
>> are doing your own caching and so on, which is part of what I wanted  
>> in this case, ie use a managed cache external to FreeMarker that  
>> other things also use instead of the cache internal to FreeMarker).
>
>>
>
>> That's another thing I definitely want to solve in FM3 (I'm not sure  
> if I want to go into that in FM2 though), but by providing a setting  
> like cfg.templateResolver (TemplateResolver interface), which has some
> minimalistic "give me a template like this somehow" method, and  
> default implementation that delegates to TemplateCache.
>
>   
>
> Being able to implement an interface and register it with the Configuration
> would be great, much better than hacking around in the implementation of
> FreeMarker while still being able to override the Template loading behavior
> completely (including caching, location resolution, etc). So yes, this sounds
> great.

Should the TemplateResolver-s (the work name for the new interface)
still get the template name already resolved to absolute and
normalized? So when cfg.getTemplate is called, then it invokes
cfg.templateNameFormat.normalizeAbsoluteName(String) to normalize the
path, and only then it calls the TemplateResolver. Also #import and
such currently calls templateNameFormat.toAbsoluteName(String,
String), and that would happen earlier than TemplateResolver is
involved.

And how would it look... perhaps like this:

    public interface TemplateResolver {

       Template getTemplate(String templatePath, Local lookupLocale, Object customLookupCondition)
       throws IOException;

    }

You may notice that it misses the `encoding` and `parsed` parameter of
cfg.getTemplate. That's because I belive that in FM3 we should not
allow specifying those as getTemplate parameters anymore, but that
will be another thread when we get there.

> -David
>
>   
>
>   
>

-- 
Thanks,
 Daniel Dekany


Re: Pluggable template retrival/caching logic (Was: Template Loader Implementation that loads from a database (DataSource))

Posted by Daniel Dekany <dd...@freemail.hu>.
Thursday, February 16, 2017, 5:33:01 PM, David E Jones wrote:

> On Thu, 2017-02-16 at 15:56 +0100, Daniel Dekany wrote:
>> Thursday, February 16, 2017, 6:17:00 AM, David E Jones wrote:
>> 
>> > 
>> > This is cleaner, more obvious what's going on underneath, but since
>> > the DefaultTemplateResolver will be the most commonly used you
>> > could just leave the current setting methods as they are and just
>> > document that if you set a different TemplateResolver they will be
>> > ignored.
>> 
>> Or they should just throw exception if the template resolver set is
>> not the default one. It can be quite annoying when someone sets the
>> templateUpdateDelay for example and it has silently no effect.
>
> Good idea, I was thinking more of calls before setting a TemplateResolver.

I would clarify there that it's the build() method that throws the
exception. Because we don't want to constraint the order in which you
set the settings. Like maybe you set the templateLoader on the
builder, and only then set the TemplateLoader to MyTemplateResolver
that doesn't support a templateLoader.

>> Also, it's maybe quite speculative, but perhaps some custom
>> TemplateResolver have some of the standard settings, like for example
>> the templateUpdateDelayMilliseconds. Then it's somewhat confusing that
>> cfg.setTemplateUpdateDelayMilliseconds doesn't work, while
>> myResolver.setTemplateUpdateDelayMilliseconds does. So I guess if we
>> keep those setters in the Configuration, then they should forward to
>> the templateResolver, if it implements the interface that contains the
>> setter.
>
> It isn't too cumbersome to have extra methods to implement, but
> would be nice to have those methods with a default implementation
> that throws the appropriate Exception. In Java 8 you can do this
> with default methods on the interface, but in Java 7- this could
> simply be an abstract class to have the same effect.

Yes, that looks to be the simplest solution. (Even if not the
cleanest... that would be introducing interfaces like
HasTemplateLoaderSetting, and so you can detect this capability
without "probing" the setter methods. Certainly an overkill anyway.)

> -David
>
>

-- 
Thanks,
 Daniel Dekany


Re: Pluggable template retrival/caching logic (Was: Template Loader Implementation that loads from a database (DataSource))

Posted by Daniel Dekany <dd...@apache.org>.
Friday, June 9, 2017, 12:19:02 AM, Daniel Dekany wrote:

[snip]
> DefaultTemplateResolver happens to support them. If
> Configuration.templateLoader is set to `new MyTemplateResolver()`, and

I meant "If Configuration.templateResolver is set to `new
MyTemplateResolver()`" of course...

-- 
Thanks,
 Daniel Dekany


Re: Pluggable template retrival/caching logic (Was: Template Loader Implementation that loads from a database (DataSource))

Posted by Daniel Dekany <dd...@apache.org>.
Now this mechanism is working in FM3. At the end I did this:

http://freemarker.org/builds/fm3/api/freemarker-core/org/apache/freemarker/core/templateresolver/TemplateResolver.html

Explanation: If you implement a custom TemplateResolver, then you are
required to declare which of the Configuration settings you support,
out of those that are related to template loading/caching. Then the
user just sets those setting on the Configuration-level, pretty much
like in FM2 (except that in FM3 you set settings in a
Configuration.Builder object, not directly in the Configuration).
DefaultTemplateResolver is not treated specially, it works just like
any custom TemplateResolver; you are allowed to set
Configuration.templateLoader,
Configuration.templateUpdateDellayMilliseconds, etc. because
DefaultTemplateResolver happens to support them. If
Configuration.templateLoader is set to `new MyTemplateResolver()`, and
MyTemplateResolver only cares about templateUpdateDellayMilliseconds,
but can't use the TemplateLoader abstraction of FM, then the user can
set templateUpdateDellayMilliseconds as usual, but can't set
Configuration.templateLoader (they get an exception that tells they
that MyTemplateResolver doesn't support the templateLoader setting).

The author of a custom TemplateResolver admittedly has to face some
extra complexity here, but I believe it's not a big deal in practice.
Also, very few developers will ever implement a custom
TemplateResolver. This thing is optimized for the users who just
configure FreeMarker.

Any insights? Like as a reality check, how well would this work with
Moqui?


Thursday, February 16, 2017, 6:33:01 PM, David E Jones wrote:

> On Thu, 2017-02-16 at 15:56 +0100, Daniel Dekany wrote:
>> Thursday, February 16, 2017, 6:17:00 AM, David E Jones wrote:
>> 
>> > 
>> > This is cleaner, more obvious what's going on underneath, but since
>> > the DefaultTemplateResolver will be the most commonly used you
>> > could just leave the current setting methods as they are and just
>> > document that if you set a different TemplateResolver they will be
>> > ignored.
>> 
>> Or they should just throw exception if the template resolver set is
>> not the default one. It can be quite annoying when someone sets the
>> templateUpdateDelay for example and it has silently no effect.
>
> Good idea, I was thinking more of calls before setting a TemplateResolver.
>
>> Also, it's maybe quite speculative, but perhaps some custom
>> TemplateResolver have some of the standard settings, like for example
>> the templateUpdateDelayMilliseconds. Then it's somewhat confusing that
>> cfg.setTemplateUpdateDelayMilliseconds doesn't work, while
>> myResolver.setTemplateUpdateDelayMilliseconds does. So I guess if we
>> keep those setters in the Configuration, then they should forward to
>> the templateResolver, if it implements the interface that contains the
>> setter.
>
> It isn't too cumbersome to have extra methods to implement, but
> would be nice to have those methods with a default implementation
> that throws the appropriate Exception. In Java 8 you can do this
> with default methods on the interface, but in Java 7- this could
> simply be an abstract class to have the same effect.
>
> -David

-- 
Thanks,
 Daniel Dekany


Re: Pluggable template retrival/caching logic (Was: Template Loader Implementation that loads from a database (DataSource))

Posted by David E Jones <de...@dejc.com>.
On Thu, 2017-02-16 at 15:56 +0100, Daniel Dekany wrote:
> Thursday, February 16, 2017, 6:17:00 AM, David E Jones wrote:
> 
> > 
> > This is cleaner, more obvious what's going on underneath, but since
> > the DefaultTemplateResolver will be the most commonly used you
> > could just leave the current setting methods as they are and just
> > document that if you set a different TemplateResolver they will be
> > ignored.
> 
> Or they should just throw exception if the template resolver set is
> not the default one. It can be quite annoying when someone sets the
> templateUpdateDelay for example and it has silently no effect.

Good idea, I was thinking more of calls before setting a TemplateResolver.

> Also, it's maybe quite speculative, but perhaps some custom
> TemplateResolver have some of the standard settings, like for example
> the templateUpdateDelayMilliseconds. Then it's somewhat confusing that
> cfg.setTemplateUpdateDelayMilliseconds doesn't work, while
> myResolver.setTemplateUpdateDelayMilliseconds does. So I guess if we
> keep those setters in the Configuration, then they should forward to
> the templateResolver, if it implements the interface that contains the
> setter.

It isn't too cumbersome to have extra methods to implement, but would be nice to have those methods with a default implementation
that throws the appropriate Exception. In Java 8 you can do this with default methods on the interface, but in Java 7- this could
simply be an abstract class to have the same effect.

-David


Re: Pluggable template retrival/caching logic (Was: Template Loader Implementation that loads from a database (DataSource))

Posted by Daniel Dekany <dd...@freemail.hu>.
Thursday, February 16, 2017, 6:17:00 AM, David E Jones wrote:

>
> This is cleaner, more obvious what's going on underneath, but since
> the DefaultTemplateResolver will be the most commonly used you
> could just leave the current setting methods as they are and just
> document that if you set a different TemplateResolver they will be
> ignored.

Or they should just throw exception if the template resolver set is
not the default one. It can be quite annoying when someone sets the
templateUpdateDelay for example and it has silently no effect.

Also, it's maybe quite speculative, but perhaps some custom
TemplateResolver have some of the standard settings, like for example
the templateUpdateDelayMilliseconds. Then it's somewhat confusing that
cfg.setTemplateUpdateDelayMilliseconds doesn't work, while
myResolver.setTemplateUpdateDelayMilliseconds does. So I guess if we
keep those setters in the Configuration, then they should forward to
the templateResolver, if it implements the interface that contains the
setter.

> -David
>
>
> On Wed, 2017-02-15 at 14:56 +0100, Daniel Dekany wrote:
>> An interesting consequence of introducing the TemplateResolver concept
>> is that it the earlier top-level configuration settings, like
>> templateLoader, templateLookupStrategy, templateNameFormat,
>> cacheStorage, and templateUpdateDelayMillisecond should now be the
>> settings (JavaBean properties) of DefaultTemplateResolver, not of
>> Configuration. In theory at least. It's the same things as with
>> ObjectWrapper, where multiple implementations are possible, and each
>> has different settings.
>> 
>> This has some inconvenient consequences for the majority who uses the
>> DefaultTemplateResolver. Earlier, you have written:
>> 
>> � cfg.setTemplateLoader(new FooTemplateLoader())
>> � cfg.setTemplateUpdateDelayMilliseconds(10_000);
>> 
>> but now you had to write either:
>> 
>> � DefaultTemplateResolver dtr = new DefaultTemplateResolver();
>> � dtr.setTemplateLoader(new FooTemplateLoader());
>> � dtr.setTemplateUpdateDelayMilliseconds(10_000);
>> � cfg.setTemplateResolver(dtr);
>> 
>> or alternatively:
>> 
>> � DefaultTemplateResolver dtr = (DefaultTemplateResolver) dtr.getTemplateResolver();
>> � dtr.setTemplateLoader(new FooTemplateLoader());
>> � dtr.setTemplateUpdateDelayMilliseconds(10_000);
>> 
>> Also configuring with j.u.Properties becomes different, because you
>> can't have this anymore:
>> 
>> � templateLoader = com.example.FooTemplateLoader
>> � templateUpdateDelay = 10s
>> 
>> I guess instead it should be something like:
>> 
>> � templateResolver.templateLoader = com.example.FooTemplateLoader
>> � templateResolver.templateUpdateDelay = 10s
>> 
>> which is a syntax that we don't yet support (dotted setting names).
>> This syntax we do support though (in FM2):
>> 
>> � templateResolver=DefaultTemplateResolver( \
>> ����������templateLoader = com.example.FooTemplateLoader, \
>> ����������templateUpdateDelayMilliseconds = 10_000 \
>> � )
>> 
>> but it has the problem that you can't, for example, set the
>> templateUpdateDelay without also specifying the whole templateResolver
>> with all of its settings. So that's where the dotted notation is
>> better. OTOH for some other things the above syntax is better, like
>> for specifying the templateConfigurations (see
>> http://freemarker.org/docs/pgui_config_templateconfigurations.html).
>> So I think we should have both, and since we must ensure that
>> templateResolver=com.example.MyTemplateResolver is "executed" earlier
>> than templateResolver.mySetting=foo anyway, if mySetting is specified
>> on both places (i.e., you have
>> templateResolver=com.example.MyTemplateResolver(mySetting="foo")
>> there), then obviously templateResolver.mySetting wins.
>> 
>> And if we support the dotted notation in j.u.Properties, that should
>> work for the objectWrapper setting too, naturally.
>> 
>> 
>> 
>

-- 
Thanks,
 Daniel Dekany


Re: Pluggable template retrival/caching logic (Was: Template Loader Implementation that loads from a database (DataSource))

Posted by David E Jones <de...@dejc.com>.
This is cleaner, more obvious what's going on underneath, but since the DefaultTemplateResolver will be the most commonly used you
could just leave the current setting methods as they are and just document that if you set a different TemplateResolver they will be
ignored.

-David


On Wed, 2017-02-15 at 14:56 +0100, Daniel Dekany wrote:
> An interesting consequence of introducing the TemplateResolver concept
> is that it the earlier top-level configuration settings, like
> templateLoader, templateLookupStrategy, templateNameFormat,
> cacheStorage, and templateUpdateDelayMillisecond should now be the
> settings (JavaBean properties) of DefaultTemplateResolver, not of
> Configuration. In theory at least. It's the same things as with
> ObjectWrapper, where multiple implementations are possible, and each
> has different settings.
> 
> This has some inconvenient consequences for the majority who uses the
> DefaultTemplateResolver. Earlier, you have written:
> 
> � cfg.setTemplateLoader(new FooTemplateLoader())
> � cfg.setTemplateUpdateDelayMilliseconds(10_000);
> 
> but now you had to write either:
> 
> � DefaultTemplateResolver dtr = new DefaultTemplateResolver();
> � dtr.setTemplateLoader(new FooTemplateLoader());
> � dtr.setTemplateUpdateDelayMilliseconds(10_000);
> � cfg.setTemplateResolver(dtr);
> 
> or alternatively:
> 
> � DefaultTemplateResolver dtr = (DefaultTemplateResolver) dtr.getTemplateResolver();
> � dtr.setTemplateLoader(new FooTemplateLoader());
> � dtr.setTemplateUpdateDelayMilliseconds(10_000);
> 
> Also configuring with j.u.Properties becomes different, because you
> can't have this anymore:
> 
> � templateLoader = com.example.FooTemplateLoader
> � templateUpdateDelay = 10s
> 
> I guess instead it should be something like:
> 
> � templateResolver.templateLoader = com.example.FooTemplateLoader
> � templateResolver.templateUpdateDelay = 10s
> 
> which is a syntax that we don't yet support (dotted setting names).
> This syntax we do support though (in FM2):
> 
> � templateResolver=DefaultTemplateResolver( \
> ����������templateLoader = com.example.FooTemplateLoader, \
> ����������templateUpdateDelayMilliseconds = 10_000 \
> � )
> 
> but it has the problem that you can't, for example, set the
> templateUpdateDelay without also specifying the whole templateResolver
> with all of its settings. So that's where the dotted notation is
> better. OTOH for some other things the above syntax is better, like
> for specifying the templateConfigurations (see
> http://freemarker.org/docs/pgui_config_templateconfigurations.html).
> So I think we should have both, and since we must ensure that
> templateResolver=com.example.MyTemplateResolver is "executed" earlier
> than templateResolver.mySetting=foo anyway, if mySetting is specified
> on both places (i.e., you have
> templateResolver=com.example.MyTemplateResolver(mySetting="foo")
> there), then obviously templateResolver.mySetting wins.
> 
> And if we support the dotted notation in j.u.Properties, that should
> work for the objectWrapper setting too, naturally.
> 
> 
> 

Re: Pluggable template retrival/caching logic (Was: Template Loader Implementation that loads from a database (DataSource))

Posted by Daniel Dekany <dd...@freemail.hu>.
An interesting consequence of introducing the TemplateResolver concept
is that it the earlier top-level configuration settings, like
templateLoader, templateLookupStrategy, templateNameFormat,
cacheStorage, and templateUpdateDelayMillisecond should now be the
settings (JavaBean properties) of DefaultTemplateResolver, not of
Configuration. In theory at least. It's the same things as with
ObjectWrapper, where multiple implementations are possible, and each
has different settings.

This has some inconvenient consequences for the majority who uses the
DefaultTemplateResolver. Earlier, you have written:

  cfg.setTemplateLoader(new FooTemplateLoader())
  cfg.setTemplateUpdateDelayMilliseconds(10_000);

but now you had to write either:

  DefaultTemplateResolver dtr = new DefaultTemplateResolver();
  dtr.setTemplateLoader(new FooTemplateLoader());
  dtr.setTemplateUpdateDelayMilliseconds(10_000);
  cfg.setTemplateResolver(dtr);

or alternatively:

  DefaultTemplateResolver dtr = (DefaultTemplateResolver) dtr.getTemplateResolver();
  dtr.setTemplateLoader(new FooTemplateLoader());
  dtr.setTemplateUpdateDelayMilliseconds(10_000);

Also configuring with j.u.Properties becomes different, because you
can't have this anymore:

  templateLoader = com.example.FooTemplateLoader
  templateUpdateDelay = 10s

I guess instead it should be something like:

  templateResolver.templateLoader = com.example.FooTemplateLoader
  templateResolver.templateUpdateDelay = 10s

which is a syntax that we don't yet support (dotted setting names).
This syntax we do support though (in FM2):

  templateResolver=DefaultTemplateResolver( \
          templateLoader = com.example.FooTemplateLoader, \
          templateUpdateDelayMilliseconds = 10_000 \
  )

but it has the problem that you can't, for example, set the
templateUpdateDelay without also specifying the whole templateResolver
with all of its settings. So that's where the dotted notation is
better. OTOH for some other things the above syntax is better, like
for specifying the templateConfigurations (see
http://freemarker.org/docs/pgui_config_templateconfigurations.html).
So I think we should have both, and since we must ensure that
templateResolver=com.example.MyTemplateResolver is "executed" earlier
than templateResolver.mySetting=foo anyway, if mySetting is specified
on both places (i.e., you have
templateResolver=com.example.MyTemplateResolver(mySetting="foo")
there), then obviously templateResolver.mySetting wins.

And if we support the dotted notation in j.u.Properties, that should
work for the objectWrapper setting too, naturally.


Tuesday, February 7, 2017, 11:59:08 AM, Daniel Dekany wrote:

> Tuesday, February 7, 2017, 7:40:18 AM, David E Jones wrote:
>
>> On Tue, 2017-01-24 at 23:47 +0100, Daniel Dekany wrote:
>>> 
>>> Should the TemplateResolver-s (the work name for the new interface)
>>> still get the template name already resolved to absolute and
>>> normalized? So when cfg.getTemplate is called, then it invokes
>>> cfg.templateNameFormat.normalizeAbsoluteName(String) to normalize the
>>> path, and only then it calls the TemplateResolver. Also #import and
>>> such currently calls templateNameFormat.toAbsoluteName(String,
>>> String), and that would happen earlier than TemplateResolver is
>>> involved.
>>> 
>>> And how would it look... perhaps like this:
>>> 
>>> ����public interface TemplateResolver {
>>> 
>>> �������Template getTemplate(String templatePath, Local lookupLocale, Object customLookupCondition)
>>> �������throws IOException;
>>> 
>>> ����}
>>> 
>>> You may notice that it misses the `encoding` and `parsed` parameter of
>>> cfg.getTemplate. That's because I belive that in FM3 we should not
>>> allow specifying those as getTemplate parameters anymore, but that
>>> will be another thread when we get there.
>>
>> IMO it should pass through the exact text from the include/etc in
>> the template. It might be worth constraining to a valid URI syntax
>> but other than that a TemplateResolver would be much more flexible if no normalization/etc is done.
>
> In FM2 there's a class like this:
>
> public abstract class TemplateNameFormat {
>     ...
>     abstract String toAbsoluteName(String baseName, String
> targetName) throws MalformedTemplateNameException;
>     abstract String normalizeAbsoluteName(String name) throws MalformedTemplateNameException;
> }
>
> My idea was that if we allow users to provide a custom implementation,
> then if the standard rules don't fit your custom TemplateResolver, you
> just create a custom TemplateNameFormat too. But now that I think
> about it more, pushing the TemplateNameFormat functionality on the
> TemplateResolver implementation does indeed look like a better
> approach, because then it can't happen that a configuration
> accidentally contains a TemplateResolver with a TemplateNameFormat
> that doesn't work well with it. But then the above two methods should
> be part of the TemplateResolver interface (because, for example, when
> you #import something, FM has to find out if the same FTL was already
> imported in the current Environment, so it needs to normalize the
> #import argument without loading anything). WDYT?
>
>> Passing in the Locale rather than trying to call it multiple times
>> with different locale extensions is a good idea too as different
>> underlying content or file stores may have their own approach for
>> this.
>
> That's even a problem with the TemplateLoader interface proposed to
> FM3. Like in the recent database template loader thread, the author
> wanted to use a separate column to indicate the locale of the template
> (and the same could happen with custom lookup conditions too), so you
> don't want to encode that information into the template name in the
> case of that particular TemplateLoader. It's something we may try to
> address in a second iteration of the FM3 TemplateLoader interface.
>
>> For example a JCR back end has quite a bit for meta data and
>> content variations.
>>
>> In general more parameters and less built into the path/name is a good thing IMO.
>
> BTW, I still want to see if in FM3 the standard TemplateResolver (the
> one that's basically FM2's TemplateCache, relies on TemplateLoader and
> TemplateLookupStrategy and TemplateNameFormat) could cover more use
> cases without becoming overly intricate. Also, even if you decide to
> use a custom TemplateResolver, perhaps you still want to call some of
> the stock TemplateLoader-s from it (while you replace the caching
> logic, etc., or load from non-TemplateLoader sources too in case of
> more sophisticated storages). I suspect you have experience with these
> things, so it would be good if you can look at the FM3 TemplateLoader
> thread.
>
>> -David
>

-- 
Thanks,
 Daniel Dekany


Re: Pluggable template retrival/caching logic (Was: Template Loader Implementation that loads from a database (DataSource))

Posted by Daniel Dekany <dd...@freemail.hu>.
Note that there's quick draft of TemplateResolver committed in the "3" branch:
https://github.com/apache/incubator-freemarker/blob/3/src/main/java/org/apache/freemarker/core/templateresolver/TemplateResolver.java

It's not integrated with the other parts of FM (it's assumed
everywhere that we have a DefaultTemplateResolver, not a generic
TemplateResolver), nor does it deal with the configuration aspects
discussed today. But it shows an idea for the main functionality.


Tuesday, February 7, 2017, 11:59:08 AM, Daniel Dekany wrote:

> Tuesday, February 7, 2017, 7:40:18 AM, David E Jones wrote:
>
>> On Tue, 2017-01-24 at 23:47 +0100, Daniel Dekany wrote:
>>> 
>>> Should the TemplateResolver-s (the work name for the new interface)
>>> still get the template name already resolved to absolute and
>>> normalized? So when cfg.getTemplate is called, then it invokes
>>> cfg.templateNameFormat.normalizeAbsoluteName(String) to normalize the
>>> path, and only then it calls the TemplateResolver. Also #import and
>>> such currently calls templateNameFormat.toAbsoluteName(String,
>>> String), and that would happen earlier than TemplateResolver is
>>> involved.
>>> 
>>> And how would it look... perhaps like this:
>>> 
>>> ����public interface TemplateResolver {
>>> 
>>> �������Template getTemplate(String templatePath, Local lookupLocale, Object customLookupCondition)
>>> �������throws IOException;
>>> 
>>> ����}
>>> 
>>> You may notice that it misses the `encoding` and `parsed` parameter of
>>> cfg.getTemplate. That's because I belive that in FM3 we should not
>>> allow specifying those as getTemplate parameters anymore, but that
>>> will be another thread when we get there.
>>
>> IMO it should pass through the exact text from the include/etc in
>> the template. It might be worth constraining to a valid URI syntax
>> but other than that a TemplateResolver would be much more flexible if no normalization/etc is done.
>
> In FM2 there's a class like this:
>
> public abstract class TemplateNameFormat {
>     ...
>     abstract String toAbsoluteName(String baseName, String
> targetName) throws MalformedTemplateNameException;
>     abstract String normalizeAbsoluteName(String name) throws MalformedTemplateNameException;
> }
>
> My idea was that if we allow users to provide a custom implementation,
> then if the standard rules don't fit your custom TemplateResolver, you
> just create a custom TemplateNameFormat too. But now that I think
> about it more, pushing the TemplateNameFormat functionality on the
> TemplateResolver implementation does indeed look like a better
> approach, because then it can't happen that a configuration
> accidentally contains a TemplateResolver with a TemplateNameFormat
> that doesn't work well with it. But then the above two methods should
> be part of the TemplateResolver interface (because, for example, when
> you #import something, FM has to find out if the same FTL was already
> imported in the current Environment, so it needs to normalize the
> #import argument without loading anything). WDYT?
>
>> Passing in the Locale rather than trying to call it multiple times
>> with different locale extensions is a good idea too as different
>> underlying content or file stores may have their own approach for
>> this.
>
> That's even a problem with the TemplateLoader interface proposed to
> FM3. Like in the recent database template loader thread, the author
> wanted to use a separate column to indicate the locale of the template
> (and the same could happen with custom lookup conditions too), so you
> don't want to encode that information into the template name in the
> case of that particular TemplateLoader. It's something we may try to
> address in a second iteration of the FM3 TemplateLoader interface.
>
>> For example a JCR back end has quite a bit for meta data and
>> content variations.
>>
>> In general more parameters and less built into the path/name is a good thing IMO.
>
> BTW, I still want to see if in FM3 the standard TemplateResolver (the
> one that's basically FM2's TemplateCache, relies on TemplateLoader and
> TemplateLookupStrategy and TemplateNameFormat) could cover more use
> cases without becoming overly intricate. Also, even if you decide to
> use a custom TemplateResolver, perhaps you still want to call some of
> the stock TemplateLoader-s from it (while you replace the caching
> logic, etc., or load from non-TemplateLoader sources too in case of
> more sophisticated storages). I suspect you have experience with these
> things, so it would be good if you can look at the FM3 TemplateLoader
> thread.
>
>> -David
>

-- 
Thanks,
 Daniel Dekany


Re: Pluggable template retrival/caching logic (Was: Template Loader Implementation that loads from a database (DataSource))

Posted by Daniel Dekany <dd...@freemail.hu>.
Tuesday, February 7, 2017, 7:40:18 AM, David E Jones wrote:

> On Tue, 2017-01-24 at 23:47 +0100, Daniel Dekany wrote:
>> 
>> Should the TemplateResolver-s (the work name for the new interface)
>> still get the template name already resolved to absolute and
>> normalized? So when cfg.getTemplate is called, then it invokes
>> cfg.templateNameFormat.normalizeAbsoluteName(String) to normalize the
>> path, and only then it calls the TemplateResolver. Also #import and
>> such currently calls templateNameFormat.toAbsoluteName(String,
>> String), and that would happen earlier than TemplateResolver is
>> involved.
>> 
>> And how would it look... perhaps like this:
>> 
>> ����public interface TemplateResolver {
>> 
>> �������Template getTemplate(String templatePath, Local lookupLocale, Object customLookupCondition)
>> �������throws IOException;
>> 
>> ����}
>> 
>> You may notice that it misses the `encoding` and `parsed` parameter of
>> cfg.getTemplate. That's because I belive that in FM3 we should not
>> allow specifying those as getTemplate parameters anymore, but that
>> will be another thread when we get there.
>
> IMO it should pass through the exact text from the include/etc in
> the template. It might be worth constraining to a valid URI syntax
> but other than that a TemplateResolver would be much more flexible if no normalization/etc is done.

In FM2 there's a class like this:

public abstract class TemplateNameFormat {
    ...
    abstract String toAbsoluteName(String baseName, String targetName) throws MalformedTemplateNameException;
    abstract String normalizeAbsoluteName(String name) throws MalformedTemplateNameException;
}

My idea was that if we allow users to provide a custom implementation,
then if the standard rules don't fit your custom TemplateResolver, you
just create a custom TemplateNameFormat too. But now that I think
about it more, pushing the TemplateNameFormat functionality on the
TemplateResolver implementation does indeed look like a better
approach, because then it can't happen that a configuration
accidentally contains a TemplateResolver with a TemplateNameFormat
that doesn't work well with it. But then the above two methods should
be part of the TemplateResolver interface (because, for example, when
you #import something, FM has to find out if the same FTL was already
imported in the current Environment, so it needs to normalize the
#import argument without loading anything). WDYT?

> Passing in the Locale rather than trying to call it multiple times
> with different locale extensions is a good idea too as different
> underlying content or file stores may have their own approach for
> this.

That's even a problem with the TemplateLoader interface proposed to
FM3. Like in the recent database template loader thread, the author
wanted to use a separate column to indicate the locale of the template
(and the same could happen with custom lookup conditions too), so you
don't want to encode that information into the template name in the
case of that particular TemplateLoader. It's something we may try to
address in a second iteration of the FM3 TemplateLoader interface.

> For example a JCR back end has quite a bit for meta data and
> content variations.
>
> In general more parameters and less built into the path/name is a good thing IMO.

BTW, I still want to see if in FM3 the standard TemplateResolver (the
one that's basically FM2's TemplateCache, relies on TemplateLoader and
TemplateLookupStrategy and TemplateNameFormat) could cover more use
cases without becoming overly intricate. Also, even if you decide to
use a custom TemplateResolver, perhaps you still want to call some of
the stock TemplateLoader-s from it (while you replace the caching
logic, etc., or load from non-TemplateLoader sources too in case of
more sophisticated storages). I suspect you have experience with these
things, so it would be good if you can look at the FM3 TemplateLoader
thread.

> -David

-- 
Thanks,
 Daniel Dekany


Re: Pluggable template retrival/caching logic (Was: Template Loader Implementation that loads from a database (DataSource))

Posted by David E Jones <de...@dejc.com>.
On Tue, 2017-01-24 at 23:47 +0100, Daniel Dekany wrote:
> 
> Should the TemplateResolver-s (the work name for the new interface)
> still get the template name already resolved to absolute and
> normalized? So when cfg.getTemplate is called, then it invokes
> cfg.templateNameFormat.normalizeAbsoluteName(String) to normalize the
> path, and only then it calls the TemplateResolver. Also #import and
> such currently calls templateNameFormat.toAbsoluteName(String,
> String), and that would happen earlier than TemplateResolver is
> involved.
> 
> And how would it look... perhaps like this:
> 
> ����public interface TemplateResolver {
> 
> �������Template getTemplate(String templatePath, Local lookupLocale, Object customLookupCondition)
> �������throws IOException;
> 
> ����}
> 
> You may notice that it misses the `encoding` and `parsed` parameter of
> cfg.getTemplate. That's because I belive that in FM3 we should not
> allow specifying those as getTemplate parameters anymore, but that
> will be another thread when we get there.

IMO it should pass through the exact text from the include/etc in the template. It might be worth constraining to a valid URI syntax
but other than that a TemplateResolver would be much more flexible if no normalization/etc is done.

Passing in the Locale rather than trying to call it multiple times with different locale extensions is a good idea too as different
underlying content or file stores may have their own approach for this. For example a JCR back end has quite a bit for meta data and
content variations.

In general more parameters and less built into the path/name is a good thing IMO. 

-David