I faced this situation quite a few times, and I found my solution but not sure if it’s a good one.
I need to call some service which interacts with the database and then share the result between multiple components.
Consider this example:
<p:outputPanel id="myPanel">
<c:set var="myVar" value="#{myService.retrieveVarFromDB(param)}" />
<my:comp1 val="#{myVar.field1}" />
<my:comp2 val="#{myVar.field2}" />
<my:comp3 val="#{myVar.field3}" />
</p:outputPanel>
Here myVar could be reevaluated multiple times, upon ajax update requests. But the good thing is that myService is called only once every time, not for every component which uses myVar. Some of my colleagues do it like this:
<my:comp1 val="#{myService.retrieveVarFromDB(param).field1}" />
<my:comp2 val="#{myService.retrieveVarFromDB(param).field2}" />
which is a total overhead. So far my solution satisfies me, but I also know that mixing JSF with JSTL tags could sometimes cause strange things to happen. And many of our co-developers try to avoid using them.
So, is there more elegant solution to this problem without using <c:set />?
Edit:
Calculating myVar just once doesn work for me, because as I stated earlier I need to reevaluate it multiple times. For example when user chooses an item from some select component, an ajax request is sent to the server which in turn makes call to the database, reevaluating myVar value.
Edit2:
myService is actually a managed bean, which uses injected EJB reference to interact with the database. I called it this way to show what it does, but that happened to be misleading. Sorry about that.
Getter calls are extraordinary cheap. They’re only expensive if you’re doing more in a getter than just returning the property. I suggest to do the job in bean’s (post) constructor instead and provide a new getter which only returns that result.
For aliasing of long EL expressions, you can always use
<ui:param>.As to mixing JSTL with JSF, they can cause view scoped beans to break and they may lead to unexpected behaviour when used in iterating JSF components such as
<ui:repeat>and<h:dataTable>. JSTL and JSF namely don’t run in sync as you’d expect from the coding. It’s JSTL which runs first from top to bottom during JSF view build time (to create the JSF component tree) and then it’s JSF which runs from top to bottom again during JSF view render time (to generate HTML).See also:
Update, as per your edit:
Just do that in the action listener method which is invoked by the ajax request. Do above all not abuse the getter for that.
with
then you can use
#{bean.myVar}in the view.