I have this sample code:
<h:form>
<h:commandButton action="#{fooBar.foo()}" value="Submit"/>
</h:form>
and in the bean:
@ManagedBean
@ApplicationScoped
public class FooBar {
public String foo() {
final Flash flash = FacesContext.getCurrentInstance().getExternalContext().getFlash();
flash.put("message", "Hello World");
return "hello?faces-redirect=true";
}
}
and finally in hello.xhtml
<h:body>
#{flash.keep.message}
</h:body>
So I go to index.xhtml, hit Submit, I get redirected to hello.xhtml as expected. And when I refresh the page I still see the message because of the flash.keep behavior which is great.
Now I am trying to understand what is going on so I open up the documentation.
There is a keep() method in this class, but its return type is void and it expects a String parameter. So is #{flash.keep.message} calling the keep() method with the message parameter? I really do not think so, as as far as I know it should have been #{flash.keep(message)}, isn't it?
So what is going on in here?
EL resolving can be customized with
ELResolverimplementations. There are two EL resolvers involved in evaluating#{flash.keep.message}. The first one, the JSF-builtinFlashELResolveris executed on#{flash}. As you can see in its source code (line numbers match Mojarra 2.2.12),the
FlashELResolverwill callELFlash.setKeepFlag(facesContext)(line 231) when the#{flash.keep}expression is evaluated. It also sets the property as resolved (line 219), so that the EL context can advance with next property, and it sets thebase(the#{flash}) as evaluated result (line 225), so effectively#{flash.keep}returns the very same#{flash}object.And then, when the
messageproperty is to be evaluated on the result of#{flash.keep}, which is essentially still#{flash}, but with the "keep" flag set, the EL-builtinMapELResolveris executed. This is because#{flash}is essentially aMap, see also the javadoc (emphasis mine).This calls the
Map#get()method, which is customized inFlashclass as below (line numbers match Mojarra 2.2.12):As you can see at line 396, it will call
keep(key)when the flag is set, as done byFlashELResolver.