Re: Configuration initialization per web request issue
Daniel Dekany <[email protected]> Sun, 10 Feb 2013 13:27:56 +0100
| Newsgroups | gmane.comp.web.freemarker.user |
|---|---|
| Message-ID | <[email protected]> |
Sunday, February 10, 2013, 1:11:43 PM, Albert Kam wrote: > 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. > 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 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... > - 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.) > 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. Yeah, that's the dirty part... but see above. -- Best regards, Daniel Dekany > On Sun, Feb 10, 2013 at 6:14 PM, Daniel Dekany <[email protected]> wrote: > Sunday, February 10, 2013, 12:07:35 PM, Albert Kam wrote: > >> 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 > > >> Thank you ! >> >> Regards from Jakarta, >> Albert >> >> >> On Sun, Feb 10, 2013 at 5:18 PM, Daniel Dekany <[email protected]> wrote: >> Sunday, February 10, 2013, 5:58:54 AM, Albert Kam wrote: >> >>> 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. >> >>> 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 ! >> >> 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