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