Discussion:
[FreeMarker-user] Configuration initialization per web request issue
Albert Kam
2013-02-10 04:58:54 UTC
Permalink
I want to use freemarker's multiple StringTemplateLoader-s per each
request. This means that i will have to new Configuration() per each
request, right ?
I wonder if this is the right way to do it, since i've read somewhere that
Configuration should be initialized once per webapp because it's expensive ?

Why do i need this approach is because i want to get locale specific
templates per request, which i put inside a properties file, and then fill
up the templates.

Example of the entry in the properties file :
my.template.key1=my.freemarker.template1.here
my.template.key2=my.freemarker.template2.here

So the logic what i have in mind is :
- i have the keys in the UI (dynamiclly obtained)
- i load templates with resourcebundle depending of current user's locale
- initialize configuration object
- setup multiple string template loaders with those i load from
resourcebundle and set them to configuration object via MultiTemplateLoader
- setup the models n get the template outputs
- print them onto UI response

All of these can happen per web request.

Is this approach appropriate ? Thank you !
--
Do not pursue the past. Do not lose yourself in the future.
The past no longer is. The future has not yet come.
Looking deeply at life as it is in the very here and now,
the practitioner dwells in stability and freedom.
(Thich Nhat Hanh)
Daniel Dekany
2013-02-10 10:18:17 UTC
Permalink
Post by Albert Kam
I want to use freemarker's multiple StringTemplateLoader-s per each
request. This means that i will have to new Configuration() per each
request, right ? I wonder if this is the right way to do it, since
i've read somewhere that Configuration should be initialized once
per webapp because it's expensive ?
The the biggest expense of not using a long-lived/shared Configuration
instance (and perhaps the only significant expense) is that you trash
the previously built template-cache each time you create a new
configuration. The template-cache stores the templates pre-parsed, so
when you request a template with Configuration.getTemplate(someName,
someLocale) for the 2nd time, FreeMarker will not load and parse it
again.
Post by Albert Kam
Why do i need this approach is because i want to get locale
specific templates per request, which i put inside a properties
file, and then fill up the templates.
my.template.key1=my.freemarker.template1.here
my.template.key2=my.freemarker.template2.here
- i have the keys in the UI (dynamiclly obtained)
- i load templates with resourcebundle depending of current user's locale
- initialize configuration object
- setup multiple string template loaders with those i load from
resourcebundle and set them to configuration object via MultiTemplateLoader
- setup the models n get the template outputs
- print them onto UI response
All of these can happen per web request.
Is this approach appropriate ? Thank you !
The template cache uses name+locale as the key to look up entries, so
just because you have different locales per request, you don't have to
give up caching. The problematic case is when the templates have no
"name" with which you can identify them, or they have but you don't
have a last modification time for them yet they are changing. In that
case you can't use the cache for *those* templates. But you can still
use the a common configuration, you just use `new Template(...)` to
create ad-hoc Template instances, instead `config.getTemplate(...)`.
The caveat with `new Template(...)` is that templates that are not
available with `config.getTemplate(...)` can't be
#include-ed/#import-ed in other templates.

Of course, to use the template-cache, you need a TemplateLoader that
stays during the whole life-cycle of the Configuration. A
StringTemplateLoader that's recreated for each request won't do. So if
you have some custom template storage, instead of filling a
StringTemplateLoader each time, maybe you can implement the
TemplateLoader interface and then do `config.setTemplateLoader(new
MyResourceBundleTemplateLoader(...))` once.
--
Best regards,
Daniel Dekany
Albert Kam
2013-02-10 11:07:35 UTC
Permalink
Your reply is very helpful. I think i understand the important points about
caching and whether it's cachable or not. This clears up about the
expensiveness without caching, having to reparse everything per request.

I just realized we can get the localized template by passing the locale in
the config.getTemplate(),
so with this, i dont need to use properties anymore.

I will just use cfg.setDirectoryForTemplateLoading() and use multiple ftl
files instead of merging all into one properties file,
therefore having the caching feature and no need for custom template loader
anymore (which in my previous idea wont work well, because all caches will
be purged if the properties file was changed, even if for just one property)

The convinience that i will lose is everything is not inside 1 file anymore
like the properties file, but i think i can cope with it with some tools.

Thank you !

Regards from Jakarta,
Albert
Post by Daniel Dekany
Post by Albert Kam
I want to use freemarker's multiple StringTemplateLoader-s per each
request. This means that i will have to new Configuration() per each
request, right ? I wonder if this is the right way to do it, since
i've read somewhere that Configuration should be initialized once
per webapp because it's expensive ?
The the biggest expense of not using a long-lived/shared Configuration
instance (and perhaps the only significant expense) is that you trash
the previously built template-cache each time you create a new
configuration. The template-cache stores the templates pre-parsed, so
when you request a template with Configuration.getTemplate(someName,
someLocale) for the 2nd time, FreeMarker will not load and parse it
again.
Post by Albert Kam
Why do i need this approach is because i want to get locale
specific templates per request, which i put inside a properties
file, and then fill up the templates.
my.template.key1=my.freemarker.template1.here
my.template.key2=my.freemarker.template2.here
- i have the keys in the UI (dynamiclly obtained)
- i load templates with resourcebundle depending of current user's locale
- initialize configuration object
- setup multiple string template loaders with those i load from
resourcebundle and set them to configuration object via
MultiTemplateLoader
Post by Albert Kam
- setup the models n get the template outputs
- print them onto UI response
All of these can happen per web request.
Is this approach appropriate ? Thank you !
The template cache uses name+locale as the key to look up entries, so
just because you have different locales per request, you don't have to
give up caching. The problematic case is when the templates have no
"name" with which you can identify them, or they have but you don't
have a last modification time for them yet they are changing. In that
case you can't use the cache for *those* templates. But you can still
use the a common configuration, you just use `new Template(...)` to
create ad-hoc Template instances, instead `config.getTemplate(...)`.
The caveat with `new Template(...)` is that templates that are not
available with `config.getTemplate(...)` can't be
#include-ed/#import-ed in other templates.
Of course, to use the template-cache, you need a TemplateLoader that
stays during the whole life-cycle of the Configuration. A
StringTemplateLoader that's recreated for each request won't do. So if
you have some custom template storage, instead of filling a
StringTemplateLoader each time, maybe you can implement the
TemplateLoader interface and then do `config.setTemplateLoader(new
MyResourceBundleTemplateLoader(...))` once.
--
Best regards,
Daniel Dekany
------------------------------------------------------------------------------
Free Next-Gen Firewall Hardware Offer
Buy your Sophos next-gen firewall before the end March 2013
and get the hardware for free! Learn more.
http://p.sf.net/sfu/sophos-d2d-feb
_______________________________________________
FreeMarker-user mailing list
https://lists.sourceforge.net/lists/listinfo/freemarker-user
--
Do not pursue the past. Do not lose yourself in the future.
The past no longer is. The future has not yet come.
Looking deeply at life as it is in the very here and now,
the practitioner dwells in stability and freedom.
(Thich Nhat Hanh)
Daniel Dekany
2013-02-10 11:14:14 UTC
Permalink
Post by Albert Kam
Your reply is very helpful. I think i understand the important
points about caching and whether it's cachable or not. This clears
up about the expensiveness without caching, having to reparse everything per request.
I just realized we can get the localized template by passing the
locale in the config.getTemplate(),
so with this, i dont need to use properties anymore.
I will just use cfg.setDirectoryForTemplateLoading() and use
multiple ftl files instead of merging all into one properties file,
therefore having the caching feature and no need for custom
template loader anymore (which in my previous idea wont work well,
because all caches will be purged if the properties file was
changed, even if for just one property)
The convinience that i will lose is everything is not inside 1 file
anymore like the properties file, but i think i can cope with it with some tools.
I suppose this is clear, but with a custom TemplateLoader you can
still put all the templates into the same file.
--
Best regards,
Daniel Dekany
Post by Albert Kam
Thank you !
Regards from Jakarta,
Albert
Post by Albert Kam
I want to use freemarker's multiple StringTemplateLoader-s per each
request. This means that i will have to new Configuration() per each
request, right ? I wonder if this is the right way to do it, since
i've read somewhere that Configuration should be initialized once
per webapp because it's expensive ?
The the biggest expense of not using a long-lived/shared Configuration
instance (and perhaps the only significant expense) is that you trash
the previously built template-cache each time you create a new
configuration. The template-cache stores the templates pre-parsed, so
when you request a template with Configuration.getTemplate(someName,
someLocale) for the 2nd time, FreeMarker will not load and parse it
again.
Post by Albert Kam
Why do i need this approach is because i want to get locale
specific templates per request, which i put inside a properties
file, and then fill up the templates.
my.template.key1=my.freemarker.template1.here
my.template.key2=my.freemarker.template2.here
- i have the keys in the UI (dynamiclly obtained)
- i load templates with resourcebundle depending of current user's locale
- initialize configuration object
- setup multiple string template loaders with those i load from
resourcebundle and set them to configuration object via MultiTemplateLoader
- setup the models n get the template outputs
- print them onto UI response
All of these can happen per web request.
Is this approach appropriate ? Thank you !
The template cache uses name+locale as the key to look up entries, so
just because you have different locales per request, you don't have to
give up caching. The problematic case is when the templates have no
"name" with which you can identify them, or they have but you don't
have a last modification time for them yet they are changing. In that
case you can't use the cache for *those* templates. But you can still
use the a common configuration, you just use `new Template(...)` to
create ad-hoc Template instances, instead `config.getTemplate(...)`.
The caveat with `new Template(...)` is that templates that are not
available with `config.getTemplate(...)` can't be
#include-ed/#import-ed in other templates.
Of course, to use the template-cache, you need a TemplateLoader that
stays during the whole life-cycle of the Configuration. A
StringTemplateLoader that's recreated for each request won't do. So if
you have some custom template storage, instead of filling a
StringTemplateLoader each time, maybe you can implement the
TemplateLoader interface and then do `config.setTemplateLoader(new
MyResourceBundleTemplateLoader(...))` once.
--
Best regards,
Daniel Dekany
Albert Kam
2013-02-10 12:11:43 UTC
Permalink
You get me rethinking again.

So if i understand correctly, i can still use a properties file to hold
multiple templates for a single locale.
My current idea is that multiple locales means multiple properties file.
And this means that my custom template loader will have to do these :
- be able to load the correct properties file based on the locale
- get the correct template based on the passed template name
- somehow be able to tell what template has changed within a single
property file.

For the template name, i can just use the property key as the name, and
return the name again as the template source, and return the property value
as the template string (as a reader instance)
For the modification date, i can just add another
<template-name>.last-modified property key.
So both are fine.

But i am still confused on how to get the correct localized properties file
from template loader.
The locale will be varied depending on my webapp's user location, so i
imagine i can call :
cfg.getTemplate(templateName, userLocale);
I am still wondering on how to access this locale reference in the custom
template loader in order to get the correct properties file.
Post by Albert Kam
Post by Albert Kam
Your reply is very helpful. I think i understand the important
points about caching and whether it's cachable or not. This clears
up about the expensiveness without caching, having to reparse everything
per request.
Post by Albert Kam
I just realized we can get the localized template by passing the
locale in the config.getTemplate(),
so with this, i dont need to use properties anymore.
I will just use cfg.setDirectoryForTemplateLoading() and use
multiple ftl files instead of merging all into one properties file,
therefore having the caching feature and no need for custom
template loader anymore (which in my previous idea wont work well,
because all caches will be purged if the properties file was
changed, even if for just one property)
The convinience that i will lose is everything is not inside 1 file
anymore like the properties file, but i think i can cope with it with
some tools.
I suppose this is clear, but with a custom TemplateLoader you can
still put all the templates into the same file.
--
Best regards,
Daniel Dekany
Post by Albert Kam
Thank you !
Regards from Jakarta,
Albert
Post by Albert Kam
I want to use freemarker's multiple StringTemplateLoader-s per each
request. This means that i will have to new Configuration() per each
request, right ? I wonder if this is the right way to do it, since
i've read somewhere that Configuration should be initialized once
per webapp because it's expensive ?
The the biggest expense of not using a long-lived/shared Configuration
instance (and perhaps the only significant expense) is that you trash
the previously built template-cache each time you create a new
configuration. The template-cache stores the templates pre-parsed, so
when you request a template with Configuration.getTemplate(someName,
someLocale) for the 2nd time, FreeMarker will not load and parse it
again.
Post by Albert Kam
Why do i need this approach is because i want to get locale
specific templates per request, which i put inside a properties
file, and then fill up the templates.
my.template.key1=my.freemarker.template1.here
my.template.key2=my.freemarker.template2.here
- i have the keys in the UI (dynamiclly obtained)
- i load templates with resourcebundle depending of current user's
locale
Post by Albert Kam
Post by Albert Kam
- initialize configuration object
- setup multiple string template loaders with those i load from
resourcebundle and set them to configuration object via
MultiTemplateLoader
Post by Albert Kam
Post by Albert Kam
- setup the models n get the template outputs
- print them onto UI response
All of these can happen per web request.
Is this approach appropriate ? Thank you !
The template cache uses name+locale as the key to look up entries, so
just because you have different locales per request, you don't have to
give up caching. The problematic case is when the templates have no
"name" with which you can identify them, or they have but you don't
have a last modification time for them yet they are changing. In that
case you can't use the cache for *those* templates. But you can still
use the a common configuration, you just use `new Template(...)` to
create ad-hoc Template instances, instead `config.getTemplate(...)`.
The caveat with `new Template(...)` is that templates that are not
available with `config.getTemplate(...)` can't be
#include-ed/#import-ed in other templates.
Of course, to use the template-cache, you need a TemplateLoader that
stays during the whole life-cycle of the Configuration. A
StringTemplateLoader that's recreated for each request won't do. So if
you have some custom template storage, instead of filling a
StringTemplateLoader each time, maybe you can implement the
TemplateLoader interface and then do `config.setTemplateLoader(new
MyResourceBundleTemplateLoader(...))` once.
--
Best regards,
Daniel Dekany
------------------------------------------------------------------------------
Free Next-Gen Firewall Hardware Offer
Buy your Sophos next-gen firewall before the end March 2013
and get the hardware for free! Learn more.
http://p.sf.net/sfu/sophos-d2d-feb
_______________________________________________
FreeMarker-user mailing list
https://lists.sourceforge.net/lists/listinfo/freemarker-user
--
Do not pursue the past. Do not lose yourself in the future.
The past no longer is. The future has not yet come.
Looking deeply at life as it is in the very here and now,
the practitioner dwells in stability and freedom.
(Thich Nhat Hanh)
Daniel Dekany
2013-02-10 12:27:56 UTC
Permalink
Post by Albert Kam
You get me rethinking again.
So if i understand correctly, i can still use a properties file to
hold multiple templates for a single locale.
Yes. FreeMarker doesn't assume that the templates are files, it just
passes the normalized path to the TemplateLoader, and gets back a
stream of bytes.
Post by Albert Kam
My current idea is that multiple locales means multiple properties file.
- be able to load the correct properties file based on the locale
This is actually a bit dirty to solve, because FreeMarker doesn't pass
the locale to the TemplateLoader, only a deduced template name like
"foo_en_US.ftl". So the TemplateLoader will have to assume that the
thing between the first "_" and ".ftl" is the locale. But I guess
that's OK...
Post by Albert Kam
- get the correct template based on the passed template name
- somehow be able to tell what template has changed within a single property file.
You don't absolutely have to do that. You can just tell that the last
modification time of a template is the same as the last modification
time of the containing file. I assume the file won't change frequently
anyway, and template parsing is quite fast actually, so who cares, if
99% of the requests are served from the cache. (It's not like with a
JSP, where re-compilation is a heavy operation.)
Post by Albert Kam
For the template name, i can just use the property key as the name,
and return the name again as the template source, and return the
property value as the template string (as a reader instance)
For the modification date, i can just add another
<template-name>.last-modified property key.
So both are fine.
But i am still confused on how to get the correct localized
properties file from template loader.
cfg.getTemplate(templateName, userLocale);
I am still wondering on how to access this locale reference in the
custom template loader in order to get the correct properties file.
Yeah, that's the dirty part... but see above.
--
Best regards,
Daniel Dekany
Post by Albert Kam
Post by Albert Kam
Your reply is very helpful. I think i understand the important
points about caching and whether it's cachable or not. This clears
up about the expensiveness without caching, having to reparse everything per request.
I just realized we can get the localized template by passing the
locale in the config.getTemplate(),
so with this, i dont need to use properties anymore.
I will just use cfg.setDirectoryForTemplateLoading() and use
multiple ftl files instead of merging all into one properties file,
therefore having the caching feature and no need for custom
template loader anymore (which in my previous idea wont work well,
because all caches will be purged if the properties file was
changed, even if for just one property)
The convinience that i will lose is everything is not inside 1 file
anymore like the properties file, but i think i can cope with it with some tools.
I suppose this is clear, but with a custom TemplateLoader you can
still put all the templates into the same file.
--
Best regards,
Daniel Dekany
Post by Albert Kam
Thank you !
Regards from Jakarta,
Albert
Post by Albert Kam
I want to use freemarker's multiple StringTemplateLoader-s per each
request. This means that i will have to new Configuration() per each
request, right ? I wonder if this is the right way to do it, since
i've read somewhere that Configuration should be initialized once
per webapp because it's expensive ?
The the biggest expense of not using a long-lived/shared Configuration
instance (and perhaps the only significant expense) is that you trash
the previously built template-cache each time you create a new
configuration. The template-cache stores the templates pre-parsed, so
when you request a template with Configuration.getTemplate(someName,
someLocale) for the 2nd time, FreeMarker will not load and parse it
again.
Post by Albert Kam
Why do i need this approach is because i want to get locale
specific templates per request, which i put inside a properties
file, and then fill up the templates.
my.template.key1=my.freemarker.template1.here
my.template.key2=my.freemarker.template2.here
- i have the keys in the UI (dynamiclly obtained)
- i load templates with resourcebundle depending of current user's locale
- initialize configuration object
- setup multiple string template loaders with those i load from
resourcebundle and set them to configuration object via MultiTemplateLoader
- setup the models n get the template outputs
- print them onto UI response
All of these can happen per web request.
Is this approach appropriate ? Thank you !
The template cache uses name+locale as the key to look up entries, so
just because you have different locales per request, you don't have to
give up caching. The problematic case is when the templates have no
"name" with which you can identify them, or they have but you don't
have a last modification time for them yet they are changing. In that
case you can't use the cache for *those* templates. But you can still
use the a common configuration, you just use `new Template(...)` to
create ad-hoc Template instances, instead `config.getTemplate(...)`.
The caveat with `new Template(...)` is that templates that are not
available with `config.getTemplate(...)` can't be
#include-ed/#import-ed in other templates.
Of course, to use the template-cache, you need a TemplateLoader that
stays during the whole life-cycle of the Configuration. A
StringTemplateLoader that's recreated for each request won't do. So if
you have some custom template storage, instead of filling a
StringTemplateLoader each time, maybe you can implement the
TemplateLoader interface and then do `config.setTemplateLoader(new
MyResourceBundleTemplateLoader(...))` once.
--
Best regards,
Daniel Dekany
Loading...