I am writing an application in Java EE 6 and using Primefaces 3.4.1 for the user interface.
I have something like this.
genericPage.xhtml
<ui:composition template="mainApplicationTemplate.xhtml" [...]> <p:tabView id="tabView" dynamic="false"cache="false"> <p:tab id="tab1" title="Tab 1"> <h:form id="form1"> ... </h:form> </p:tab> <p:tab id="tab1" title="Tab 1"> <h:form id="form2"> ... </h:form> </p:tab> </p:tabView> <ui:composition >
child1.xmtml
<ui:composition template="genericPage.xhtml" ...> <ui:param name="actionBean" value="#{actionBeanA}"/> </ui:compisition>
child2.xmtml
<ui:composition template="genericPage.xhtml" ...> <ui:param name="actionBean" value="#{actionBeanB}"/> </ui:compisition>
The idea is that child1.xhtml and child2.xhtml use the same jsf code, all of which are contained in the genericPage.xhtml file, but they have different bean backends (parameterized "actionBean")
So far it works very well. This gets complicated when I set the ui parameter inside the <p:ajax/> element.
From the bean backend, I need to programmatically update the active tab, leaving the other untouched. To do this, I need to keep the active tab in the bean action. When certain external events occur, the bean action updates the active tabs.
Please note that due to some other factors:
- I cannot set
dynamic="true" in tabView - I cannot have a global shape around a
tabView and therefore cannot use the activeIndex property (which I do in another part of the application) to control the active tab.
What i want to do
To solve this problem, I want to use the tabChange event of the tabChange element:
<p:tabView id="tabView" dynamic="false"cache="false"> <p:ajax event="tabChange" listener="#{actionBean.listen}" <p:tab id="tab1" title="Tab 1"> <h:form id="form1"> ... </h:form> </p:tab> <p:tab id="tab1" title="Tab 1"> <h:form id="form2"> ... </h:form> </p:tab> </p:tabView>
action bean
@Named @WindowScoped public class ActionBeanA implements Serializable{ public void listen(TabChangeEvent event){ ... } }
What does not work
When I do this, I get an error
Target Unreachable, identifier 'actionBean' resolved to null: javax.el.PropertyNotFoundException: Target Unreachable, identifier 'actionBean' resolved to null
This, apparently, indicates that the <p:ajax> element did not pass the bean action and therefore does not know what the actionBean .
However, if I change the signature of a listener method like
<p:ajax event="tabChange" listener="#{actionBean.listen(anything)}"
and change the bean backend to something like:
public void listen(TabChangeEvent event){ System.out.println(event.toString()); }
By doing this, I do not get an invalid target error, but a null pointer exception in the listening method (because I did not assign the value "nothing"). This shows that in this case the <p:ajax/> elements know that actionBean is an actionBean and it is possible to call the method in the bean.
Questions
How could I get around this? I would like to be able to send a new active tab to my backend bean in the tab change event.