Cannot successfully update backing bean when not in main page - jsf

I am new with JSF/PrimeFacesand now, I'm trying to solve this problem for days.
I have a page with a commandLink which opens a dialog with a TreeTable that displays values from the backing bean. The value of the bean is updated depending on the product.url.
My problem is, I get a successful result when I click on the commandLink from the main page or landing page(/products.xhtml?...ver=2019.000), but when I'm on the other redirected links(/products.xhtml?...ver=2018.000), it just won't work. The passed #{DownloadView.path} is null.
Here's a snippet of my .xhtml with the commandLink:
<div id="features">
<h:form id="form">
<div class="feature-icon fadeInDown animated" style="margin:0px 35px">
<p:commandLink action="/products.xhtml?faces-redirect=true&ver=2019.000" value="2019.000" style="#{fn:startsWith(ProductsView.actVer, '2019.000') ? 'background-color: #e91e63;' : ''}" />
</div>
<div class="feature-icon fadeInDown animated" style="margin:0px 35px">
<p:commandLink action="/products.xhtml?faces-redirect=true&ver=2018.000" value="2018.000" style="#{fn:startsWith(ProductsView.actVer, '2018.000') ? 'background-color: #e91e63;' : ''}" />
</div>
</h:form>
</div>
<div id="promotion" class="clearfix">
. . .
<ui:fragment rendered="#{!empty product.url}">
<ui:fragment rendered="#{fn:startsWith(product.url, 'file')}">
<h:outputText value="#{product.url}"/>
<p:commandLink action="#{DownloadView.listFiles}" update=":download-form:downloadPanel" oncomplete="PF('downloadDialog').show()" title="Details" >
<h:outputText value="#{product.name}" />
<f:setPropertyActionListener target="#{DownloadView.path}" value="#{product.url}" />
</p:commandLink>
</ui:fragment>
</ui:fragment>
. . .
</div>
Here's my dialog:
<h:form id="download-form" >
<p:dialog id="dialog" header="Details" showEffect="fade" widgetVar="downloadDialog" modal="true" resizable="false" dynamic="true">
<p:outputPanel id="downloadPanel">
<p:treeTable value="#{DownloadView.root}" var="download" style="margin-top:0" scrollable="true" scrollHeight="300">
<f:facet name="header">
Document Viewer
</f:facet>
<p:column headerText="Name">
<a href="#{download.path}" > <h:outputText value="#{download.name}" /> </a>
</p:column>
<p:column headerText="Location">
<h:outputText value="#{download.path}" />
</p:column>
</p:treeTable>
</p:outputPanel>
<p:ajax event="open" listener="#{DownloadView.reset()}"/>
</p:dialog>
</h:form>
Here's my DownloadView class:
#SessionScoped
public class DownloadView {
private TreeNode root;
private String path;
private DownloadBI downloadBI;
#PostConstruct
public void init() {
downloadBI = new DownloadBI();
}
public void listFiles() {
downloadBI.setPath(path);
this.root = downloadBI.getFilesTreeNode();
}
public TreeNode getRoot() {
return root;
}
public void setRoot(TreeNode root) {
this.root = root;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public void reset() {
this.path = "";
this.root = null;
}
}
When I click on the commandLink from the landing page, the TreeTable is populated and checking the logs, the path is set:
But, if I click on the commandLink, other than the landing page, the TreeTable is empty and path is not set.
Any idea to resolve this problem is greatly appreciated! Thank you!

Related

Primefaces Bean Object isn't updated correctly

I've got the following issue. I have a XHTML:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
template="../layout.xhtml">
<ui:define name="header">
<div id="header">
Abfragen
</div>
</ui:define>
<ui:define name="main">
<p:toolbar>
<p:toolbarGroup>
<p:commandButton value="Neu" icon="pi pi-plus" actionListener="#{abfrageHandler.newAbfrage}"
update="manage-queries-content" oncomplete="PF('manageQueriesDialog').show()"
styleClass="ui-button-success" style="margin-right: .5rem">
<p:resetInput target=":ucmdbform:ucmdbtab:manage-ucmdb-queries-content"/>
</p:commandButton>
</p:toolbarGroup>
</p:toolbar>
<p:dataTable id="dt-queries" widgetVar="dtQueries" reflow="true" showGridlines="true" size="small"
var="querie" value="#{abfrageHandler.abfragen}">
<p:column headerText="Abfrage">
<h:outputText value="#{querie.name}" />
</p:column>
<p:column headerText="TQL">
<h:outputText value="#{querie.tql}" />
</p:column>
<p:column headerText="Zyklus">
<h:outputText value="#{querie.zyklus}" />
</p:column>
<p:column headerText="Typ">
<h:outputText value="#{querie.typ}" />
</p:column>
<p:column exportable="false">
<p:commandButton icon="pi pi-pencil" update="manage-queries-content"
oncomplete="PF('manageQueriesDialog').show()"
styleClass="edit-button rounded-button ui-button-success" process="#this">
<f:setPropertyActionListener value="#{querie}" target="#{abfrageHandler.selected}"/>
<p:resetInput target="manage-queries-content"/>
</p:commandButton>
<p:commandButton icon="pi pi-search" actionListener="#{abfrageHandler.startAbfrage(querie)}"
styleClass="edit-button rounded-button ui-button-success" process="#this">
</p:commandButton>
<p:commandButton class="ui-button-warning rounded-button" icon="pi pi-trash" process="#this"
oncomplete="PF('deleteQuerieDialog').show()">
<f:setPropertyActionListener value="#{querie}" target="#{abfrageHandler.selected}"/>
</p:commandButton>
</p:column>
</p:dataTable>
<p:dialog header="Abfrage" showEffect="fade" modal="true" width="600px"
widgetVar="manageQueriesDialog" responsive="true">
<p:outputPanel id="manage-queries-content" class="ui-fluid">
<p:outputPanel rendered="#{not empty abfrageHandler.selected}">
<div class="p-field">
<p:outputLabel for="abfName">Name</p:outputLabel>
<p:inputText id="abfName" value="#{abfrageHandler.selected.name}" required="true"/>
</div>
<div class="p-field">
<p:outputLabel for="abfTql">TQL</p:outputLabel>
<p:inputText id="abfTql" value="#{abfrageHandler.selected.tql}" required="true"/>
</div>
<div class="p-field">
<p:outputLabel for="abfZyklus">Zyklus</p:outputLabel>
<p:inputText id="abfZyklus" value="#{abfrageHandler.selected.zyklus}" required="true"/>
</div>
<div class="p-field">
<p:outputLabel for="#next">Abfrageart</p:outputLabel>
<p:selectOneMenu id="abfTyp" value="#{abfrageHandler.selected.typ}" required="false">
<f:selectItem itemLabel="Eins wählen" itemValue=""/>
<f:selectItems value="#{abfrageHandler.requestResolutions}" var="reso"
itemLabel="#{reso.toString()}" itemValue="#{reso}"/>
</p:selectOneMenu>
</div>
</p:outputPanel>
</p:outputPanel>
<f:facet name="footer">
<p:commandButton value="Speichern" icon="pi pi-check" actionListener="#{abfrageHandler.saveAbfrage}"
update="manage-queries-content" process="manage-queries-content #this"/>
<p:commandButton value="Abbruch" icon="pi pi-times" onclick="PF('manageQueriesDialog').hide()"
class="ui-button-secondary"/>
</f:facet>
</p:dialog>
<p:confirmDialog widgetVar="deleteQuerieDialog" showEffect="fade" width="300"
message="TQL wirklich löschen?" header="Bestätigen" severity="warn">
<p:commandButton value="Ja" icon="pi pi-check" actionListener="#{abfrageHandler.deleteParameter}"
process="#this" oncomplete="PF('deleteQuerieDialog').hide()"/>
<p:commandButton value="Nein" type="button" styleClass="ui-button-secondary" icon="pi pi-times"
onclick="PF('deleteQuerieDialog').hide()"/>
</p:confirmDialog>
</ui:define>
</ui:composition>
And the following bean in the backend:
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import org.primefaces.PrimeFaces;
import main.java.ucmdbtool.RequestResolutions;
import main.java.ucmdbtool.UcmdbAbfrageInteface;
import main.java.ucmdbtool.table.Abfrage;
import main.java.ucmdbtool.table.UcmdbAbfTableHandler;
#SuppressWarnings("serial")
#Named("abfrageHandler")
#ViewScoped
public class AbfrageHandler implements Serializable {
private List<Abfrage> abfragen = new ArrayList<>();
private Abfrage selected;
private RequestResolutions[] requestResolutions;
#PostConstruct
private void init() {
abfragen = UcmdbAbfTableHandler.getAbfragen();
requestResolutions = RequestResolutions.values();
}
public void newAbfrage() {
selected = new Abfrage();
}
public void saveAbfrage() {
if (selected.getPk() == null) {
selected.setPk(UUID.randomUUID());
UcmdbAbfTableHandler.insertAbfrage(selected);
abfragen.add(selected);
}
else {
UcmdbAbfTableHandler.updateAbfrage(selected);
}
PrimeFaces.current().executeScript("PF('manageQueriesDialog').hide()");
PrimeFaces.current().ajax().update("dt-queries");
}
public void startAbfrage(Abfrage abf) {
UcmdbAbfrageInteface.doRequest(abf);
}
public void deleteAbfrage() {
if(selected != null) {
UcmdbAbfTableHandler.deleteAbfrage(selected);
abfragen.remove(selected);
}
PrimeFaces.current().ajax().update("dt-queries");
}
public List<Abfrage> getAbfragen() { return abfragen; }
public Abfrage getSelected() { return selected; }
public RequestResolutions[] getRequestResolutions() { return requestResolutions; }
public void setSelected(Abfrage selected) { this.selected = selected; }
}
I've included all imports, because maybe one is off a false package. My problem is, if I click on new the dialog stays empty, because he thinks the object is empty. When I click on the edit button the object is loaded, but I can't save it because abfTyp is empty (it was required="true"), after I set required to false I could save, but my object had the old data and not the date I had changed. I have an almost similar page which is working fine and I can't find the difference. RequestResolutions is a stupid ENUM without any functions.
The dialog is empty when using "neu" because you create a new version of "selected" each time. The old data is reappearing on "edit" because the previous time failed the validation, but you immediately close the dialog. Then you use p:resetInput which resets back to the stored value. If the selectList value is empty, it means that what's coming from the data source does not match any values in the Enum select list that you provide.
I had a number of issues getting the sample to work... missing form, update= having bad references. But I think the main design issue is that you're not displaying any validation errors in the dialog - just closing the dialog window immediately. And, by the way, you should mostly be using action= on command buttons, not actionListener=. See here to understand why. All field validation will have passed before the action method gets executed.
I suggest the following amendments:
<p:commandButton value="Neu" icon="pi pi-plus" action="#{abfrageHandler.newAbfrage}"
update=":ucmdbform:manage-queries-content"
oncomplete="PF('manageQueriesDialog').show()"
styleClass="ui-button-success" style="margin-right: .5rem">
<!-- <p:resetInput target=":ucmdbform:manage-queries-content"/> -->
</p:commandButton>
.
.
<p:commandButton value="Speichern" icon="pi pi-check"
action="#{abfrageHandler.saveAbfrage}"
update=":ucmdbform:dt-queries :ucmdbform:manage-queries-content"
oncomplete="if ( args.saved == 1 ) { PF('manageQueriesDialog').hide()};"/>
Plus all actionListeners="..." --> action="..."; plus add p:message to all dialog fields that could possibly fail validation.
public void saveAbfrage() {
if (selected.getPk() == null) {
selected.setPk(UUID.randomUUID());
UcmdbAbfTableHandler.insertAbfrage(selected);
abfragen.add(selected);
} else {
UcmdbAbfTableHandler.updateAbfrage(selected);
}
PrimeFaces.current().ajax().addCallbackParam("saved", 1);
// PrimeFaces.current().ajax().update(":ucmdbform:dt-queries");
// PrimeFaces.current().executeScript("PF('manageQueriesDialog').hide();");
}

PrimeFaces p:idleMonitor rendered="false" not working

I am developing a project with Primefaces 5.1.
In my project, I used p:idleMonitor, on my Start button click the p:idleMonitor rendered="true" is working .
On my Stop button click the p:idleMonitor rendered="false" not working and the p:idleMonitor is still processing.
Sample Code:
index.xhtml
<p:panel id="mainPanelId">
<p:commandButton value="Start" update="mainPanelId" action="{Sample.start}"/>
<p:commandButton value="Stop" update="mainPanelId" action="#{Sample.stop}"/>
<p:idleMonitor timeout="5000" rendered="#{Sample.idleRendered}">
<p:ajax event="idle" oncomplete="PF('dialogId').show();"/>
<p:ajax event="active" oncomplete="PF('dialogId').hide();"/>
</p:idleMonitor>
<p:dialog id="dialogId" widgetVar="dialogId" header="Idle">
<p:outputLabel value="Idle Mode Actived!"/>
</p:dialog>
</p:panel>
Sample.java
class Sample
{
private boolean idleRendered;
public String start()
{
idleRendered = true;
return null;
}
public String stop()
{
idleRendered = false;
return null;
}
}
A few things you should do differently.
Use <h:form>
Use actionListener by p:commandButton and void methods of your bean
XHTML
<h:form>
<p:panel id="mainPanelId">
<p:commandButton value="Start" update="mainPanelId"
actionListener="#{Sample.start}" />
<p:commandButton value="Stop" update="mainPanelId"
actionListener="#{Sample.stop}" />
<h:outputText value="#{Sample.idleRendered}" />
<p:idleMonitor timeout="5000" rendered="#{Sample.idleRendered}">
<p:ajax event="idle" oncomplete="PF('dialogId').show();" />
<p:ajax event="active" oncomplete="PF('dialogId').hide();" />
</p:idleMonitor>
<p:dialog id="dialogId" widgetVar="dialogId" header="Idle">
<p:outputLabel value="Idle Mode Actived!" />
</p:dialog>
</p:panel>
</h:form>
Bean
#Named("Sample")
#SessionScoped
public class Sample implements Serializable {
private boolean idleRendered = true;
public void start() {
idleRendered = true;
}
public void stop() {
idleRendered = false;
}
public boolean isIdleRendered() {
return idleRendered;
}
public void setIdleRendered(boolean idleRendered) {
this.idleRendered = idleRendered;
}
}
Update:
Looks like a bug, here is a workaround:
<p:outputPanel rendered="#{Sample.idleRendered}">
<p:idleMonitor timeout="5000">
<p:ajax event="idle" oncomplete="PF('dialogId').show();" />
<p:ajax event="active" oncomplete="PF('dialogId').hide();" />
</p:idleMonitor>
</p:outputPanel>

primefaces commandlink wont show modal dialog

hello I have a commandLink that executes a method in my baking bean, that method calls an ejb that builds a string and place it as an attribute of the bean (with getters and setters), after executing that method should raise a modal dialog to only display the value of that attribute but it does not, I see the method that builds the chain runs but does not lift the dialogue, this is my code:
xhtml:
<ui:composition>
<p:panelGrid columns="3" style="width: 100%" >
<h:form id="headerForm">
<p:column style="width: 15%;height:auto; text-align: center;">
<p:graphicImage value="#{loginBean.url}" style="align:center;"/>
</p:column>
<p:column>
<div align="center">
<h:outputText styleClass="titleHeader" value="#{loginBean.entityName}" />
</div>
</p:column>
<p:column style="width: 15%;height:auto; text-align: center;">
<div align="right">
<h:commandLink onComplete="PF('dlg').show(); return false;" type="button" ajax="false" action="# {xxxxBean.createString}">
<h:outputText value="Contact" />
</h:commandLink>
</div>
</p:column>
</h:form>
</p:panelGrid>
<p:dialog id="dlg" header="Some title here" widgetVar="dlg" modal="true">
<h:outputText value="#{xxxxBean.stringBuild}" />
</p:dialog>
</ui:composition>
Backing bean:
#ManagedBean
#SuppressWarnings("serial")
public class XxxxBean implements Serializable{
private String stringBuild;
private someBeanRemote ejb;
public XxxxBean() {
// TODO Auto-generated constructor stub
try{
ejb = EjbConsumer.getRemoteEjb();
}catch(Exception e){
e.printStackTrace();
}
}
public void createString(){
List<someObject> list = ejb.findAllActiveObjects(Constants.TOP);
String temp = "";
if( list!=null && list.size() > 0 ){
for(int i=0; i < list.size(); i++){
temp += list.get(i).getName() + "<br/>";
}
this.stringBuild= temp;
}
System.out.println(this.stringBuild);
}
public void setStringBuild(String stringBuild) {
this.stringBuild= stringBuild;
}
public String getStringBuild() {
return stringBuild;
}
}
thanks in advance!!!
You are using ajax=false with oncomplete
oncomplete: Client side callback to execute when ajax request is completed.
Change to:
<p:commandLink oncomplete="PF('dlg').show();" action="#{yourBean.youraction}"></p:commandLink>
that is default ajax = true and everything should work

f:setPropertyActionListener does not set property

I am lost. I researched almost every post about setPropertyListener and I do not know what I'm doing wrong. I have this JSF Page:
<ui:define name="content">
<h:form id="itemSearchForm">
<p:commandButton update=":itemForm"
icon="ui-icon ui-icon-search">
<f:setPropertyActionListener target="#{itemDetailManagedBean.itemId}"
value="test"/>
<f:setPropertyActionListener target="#{itemDetailManagedBean.accountType}"
value="test"/>
</p:commandButton>
<p:dataTable id="itemList"
paginator="true"
var="currentItem"
value="#searchItemManagedBean.searchItems}">
.
.
<p:column headerText="Detail">
<p:commandButton update=":itemForm"
oncomplete="PF('itemDetail').show()"
icon="ui-icon ui-icon-search">
<f:setPropertyActionListener target="#{itemDetailManagedBean.itemId}"
value="test"/>
<f:setPropertyActionListener target="#{itemDetailManagedBean.accountType}"
value="test"/>
</p:commandButton>
</p:column>
</p:dataTable>
</h:form>
</ui:define>
and itemDetailManagedean:
public class ItemDetailManagedBean implements Serializable{
private String itemId,accountType;
public ItemDetailManagedBean() {
}
public SearchForItemBean getSearchBean() {
return searchBean;
}
public String getItemId() {
return itemId;
}
public String getAccountType() {
return accountType;
}
public void setItemId(String itemId) {
this.itemId = itemId;
}
public void setAccountType(String accountType) {
this.accountType = accountType;
}
}
The problem is, that the first commandButton is working as it should(so it set the properties right). But the second commandButton does not work at all. Both button shows dialog, as they should. I have itemForm on the other part of page.
Got the sollution finally. The problem was actually not in the JSF but in ServiceBean, which had changed the data table content during the loading.

How to expand all the nodes of treeTable?

I have a tree table and two buttons:
one for collapsing the tree and
the other for expanding,
but they don't work. At the backing bean I did root.setExpanded(true); and root.setExpanded(false); but it doesn't work.
<center>
<p:treeTable value="#{roleMB.root}" var="roleTreeTableVar"
binding="#{roleMB.treeTable}" id="roleTreeTable">
<f:facet name="header">
<center>
<p:commandButton value="Réduire tout"
icon="ui-icon-folder-collapsed" style="font-size: 0.9em"
actionListener="#{roleMB.expandAll}"
update=":roleTreeTableForm:roleTreeTable" />
<p:spacer width="30px" />
<p:commandButton value="Développer tout"
icon="ui-icon-folder-open" style="font-size: 0.9em"
actionListener="#{roleMB.collapseAll}"
update=":roleTreeTableForm:roleTreeTable" />
<p:spacer width="30px" />
</center>
</f:facet>
<p:column style="width:150px">
<f:facet name="header">
Nom de Role
</f:facet>
<h:outputText value="#{roleTreeTableVar.nom}" />
</p:column>
<p:column style="width:100px">
<f:facet name="header">
Id de role
</f:facet>
<h:outputText value="#{roleTreeTableVar.id}" />
</p:column>
<p:column style="width:20px">
<p:commandLink oncomplete="dlgAddRole.show()" value="Ajouter"
update=":addRoleForm:selectRolesNamesId">
<f:setPropertyActionListener value="#{roleTreeTableVar}"
target="#{roleMB.selectedRole}" />
</p:commandLink>
<p:commandLink oncomplete="delRole.show()" value="Supprimer">
<f:setPropertyActionListener value="#{roleTreeTableVar}"
target="#{roleMB.selectedRole}" />
</p:commandLink>
<p:commandLink oncomplete="editRole.show()" value="Modifier">
<f:setPropertyActionListener value="#{roleTreeTableVar}"
target="#{roleMB.selectedRole}" />
</p:commandLink>
</p:column>
</p:treeTable>
</center>
This is recursive method for Collapse and Expande.
public void collapsingORexpanding(TreeNode n, boolean option) {
if(n.getChildren().size() == 0) {
n.setSelected(false);
}
else {
for(TreeNode s: n.getChildren()) {
collapsingORexpanding(s, option);
}
n.setExpanded(option);
n.setSelected(false);
}
}
The variable n is the node than you want to expand or colapse.
When The variable option is false, all children of the n is
collapse, in the another case, is expanded
setSelected(false) indicate than this node isn't selected
You should set the expanded property to true not just for the root node but for all the children nodes as well.
A possible solution might look this:
view.xhtml
<h:form id="form">
...
<p:commandButton update=":form:tree" actionListener="#{view.collapseAll}"
icon="fa fa-minus" title="#{msg.collapseAll}"/>
<p:commandButton update=":form:tree" actionListener="#{view.expandAll}"
icon="fa fa-plus" title="#{msg.expandAll}"/>
...
<p:treeTable id="tree" ...>
...
</p:treeTable>
...
</h:form>
View.java
#Named
#ViewScoped
public class View implements Serializable {
private TreeNode root;
...
public void collapseAll() {
setExpandedRecursively(root, false);
}
public void expandAll() {
setExpandedRecursively(root, true);
}
private void setExpandedRecursively(final TreeNode node, final boolean expanded) {
for (final TreeNode child : node.getChildren()) {
setExpandedRecursively(child, expanded);
}
node.setExpanded(expanded);
}
}
For question: "how can this be realized?"
In code...
public void reloadTree() {
assocRoot = new DefaultTreeNode();
assocRoot.setExpanded(true);
TreeNode currentAssocNode;
AbstractDocument parentAssoc = getParentDocAssociation();
if(parentAssoc !=null) {
TreeNode parentAssocNode = new DefaultTreeNode(parentAssoc);
parentAssocNode.setExpanded(true);
....

Resources