Due to a given requirement to show a header from an external source, we came up with the following setup (using JEE6 on Tomcat 7):
Our pages use a template regularly:
...
<ui:composition ... template="/WEB-INF/templates/template.xhtml">
...
This template additionally to laying out the structure of the page includes another XHTML file in its body:
...
<h:body>
<ui:include src="./header.xhtml" />
...
And then the included file again uses a template, but this time pointing to an external resource which returns a <div> element containing the to be used header:
...
<ui:composition ... template="http://someserver/somefile">
...
I know that this setup is a bit strange, but the indirection was necessary in order to include the externally generated <div> element which we had to include in our page. (In case someone can provide a smarter solution to the given problem, I'll be happy.)
This works fine so far, but it seems to be the case, that this included file gets cached by our Tomcat resulting in not showing the current header after it was changed. If Tomcat gets restarted, the new header gets shown.
Can someone give me some insight how this all works under the hood and if it's related to Facelets, Tomcat or my specific setup?
There are multiple solutions on different levels, that you might use: You could just implement a ResourceResolver and include a template from a defined URL (with a defined URL like external-resource/header.xhtml). This ResourceResolver might be configured with the external reference.
The next possibility would be to have a ServletFilter that post processes your HTML and adds the header at a defined position.
And finally you could implement a simple custom component to load the header either on server or on client side using jQuery or such.
You generally don't want to disable caching on the facelets since it will decrease performance.
In JSF 2 (i.e. in Facelets), a template is a static piece of content that can have dynamic content composed within it.
If you want to use a different template, firstly you have to point to a different page with a different URL path, then the different page can use a different template:
<ui:include src="./header{$HeaderTemplateSuffix}.xhtml" />
Then headerABC.xml can have:
...
<ui:composition ... template="http://someserver/somefileABC">
...
and headerDEF.xml can have
...
<ui:composition ... template="http://someserver/somefileDEF">
...
Alternatively, you could abandon using templates against headers, and generate all header content dynamically (even including the static parts).
Note: merging html header template back into the main template is NOT a solution to this problem, because it doesn't address the core challenge of the header template being dynamic.
Hope that helps! Cheers :^)
Note: it is possible to set the following in web.xml:
<!-- Time in seconds that facelets should be checked for changes since last request. A value of -1 disables refresh checking. -->
<context-param>
<param-name>javax.faces.FACELETS_REFRESH_PERIOD</param-name>
<param-value>0</param-value>
</context-param>
<!-- Set the project stage to "Development", "UnitTest", "SystemTest", or "Production". -->
<!-- An optional parameter that makes troubleshooting errors much easier. -->
<!-- You should remove this context parameter before deploying to production! -->
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
HOWEVER, that is intended to serve a whole different purpose: to allow the developer to change any static resource on-the-fly and the JSF container will dynamically check for changes and load it during development. It is not an intention that you use this to simulate dynamic templating, and setting the above properties will have a negative impact on performance and secure behaviour in your Production environment.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With