I have a composite component:
<cc:interface componentType="com.example.MyComponent">
<!-- ... -->
</cc:interface>
<cc:implementation>
<f:phaseListener binding="#{cc}"/>
<div id="#{cc.clientId}">
<!-- ... -->
</div>
</cc:implementation>
And its class:
@FacesComponent("com.example.MyComponent")
public class MyComponent extends UIOutput implements NamingContainer, PhaseListener
{
@Override
public String getFamily()
{
return "javax.faces.NamingContainer";
}
@Override
public PhaseId getPhaseId()
{
return PhaseId.ANY_PHASE;
}
@Override
public void beforePhase(PhaseEvent event)
{
// Do something ...
}
@Override
public void afterPhase(PhaseEvent event)
{
// Do something ...
}
}
Neither the beforePhase(PhaseEvent)
nor afterPhase(PhaseEvent)
methods are called in any case, be it a full or partial page load.
I note this bug here: http://java.net/jira/browse/JAVASERVERFACES-1200, but it seems to have been fixed quite a while ago.
I'm using GlassFish 3.1.2.2 on Java 6u33 x64.
The #{cc}
is re-evaluated everytime when the beforePhase()
or afterPhase()
method of the <f:phaseListener>
actually needs to be executed by the UIViewRoot
. The #{cc}
is not available in the EL scope at that moment. It's only available within the component's scope.
It works fine if the binding
points to at least a request scoped variable like as follows in the composite component's constructor:
public MyComponent() {
FacesContext.getCurrentInstance().getExternalContext().getRequestMap().put("ccc", this);
}
with
<f:phaseListener binding="#{ccc}" />
This construct only fails if you've multiple composite components of this type, of course.
You'd better look for an alternate approach: get rid of the <f:phaseListener>
altogether and just use UIViewRoot#addPhaseListener()
in the composite component's constructor:
public MyComponent() {
FacesContext.getCurrentInstance().getViewRoot().addPhaseListener(this);
}
Unrelated to the concrete problem, better use UINamingContainer.COMPONENT_FAMILY
constant instead of hardcoding "javax.faces.NamingContainer"
.