JSF 2.2 #ViewScoped binding bug? - jsf

I've read about the binding bug with #ViewScoped (BUG REPORT) and that it was fixed in one of the latest versions of JSF, so I tested this with the 3 latest versions of JSF and tried using the
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>false</param-value>
fix to solve it, but no luck.
I have a primefaces datatable where I have filters in each column header.
<p:column id="cpfHeader" sortBy="#{cliente.nrCpf}"
filterMatchMode="contains">
<f:facet name="header">
<h:panelGrid columns="1">
<h:outputText value="CPF" />
<p:inputText value="#{cadastroClienteBean.cliente.nrCpf}">
</p:inputText>
<p:commandButton
actionListener="#{cadastroClienteBean.getClientesBusca}"
update="#{form}:tabelaCliente:tblCliente" value="Filtrar"></p:commandButton>
</h:panelGrid>
</f:facet>
#{cliente.nrCpf}
</p:column>
Before I changed the JSF version, everytime I'd click on the "Filtrar" button, a new instance of my cadastroClienteBean would be created. Now that I've changed it, it seems that the ManagedBean is not being instantiated everytime, but the cliente variable is becoming null, eventhough I instantiate it on the constructor.
public CadastroClienteBean(){
cliente = new Cliente();
init();
}
EDIT: After debugging a bit I found out that the value of the filter is being set on the variable and right after that the setCliente() is being called and setting it to null, but I don't know why.

Figured out what was happening the selection="#{cadastroClienteBean.cliente}" attribute on the dataTable was setting the client to null since there was no line selected.

Related

Primefaces 8.0 JSF not updating table [duplicate]

This question already has answers here:
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
(6 answers)
Closed 2 years ago.
When I click addTagButton, everything works well. It updates all three components: tags, tagId and addTagButton.
<p:commandButton id="addTagButton" icon="ui-icon-plus"
action="#{searchBean.addTag}"
update="tags, tagId, addTagButton"
disabled="#{searchBean.tagChoices.size() == 0}">
</p:commandButton>
Here's the table component:
<h:dataTable id="tags" var="tag" value="#{searchBean.tags}">
<h:column>
<div style="text-align:right;">
<h:outputLabel value="#{tag.typeName}:"/>
</div>
</h:column>
<h:column>
<p:inputText id="tag" size="25" value="#{tag.typeValue}"
disabled="#{searchBean.searchForParent}"/>
</h:column>
<h:column>
<p:commandButton id="delTagButton" icon="pi pi-trash"
action="#{searchBean.deleteTag}"
update=":contentForm:tagId, :contentForm:addTagButton, tags">
<f:setPropertyActionListener
target="#{searchBean.tagId}"
value="#{tag.typeName}" />
</p:commandButton>
</h:column>
</h:dataTable>
When i click on delTagButton that is on each row in tags table, action works fine, :contentForm:tagId and :contentForm:addTagButton update fine. But tags table which is where clicked command button exist, does not update.
When a row is deleted, change must reflect in the tags table which does not work.
Now, If I change h:dataTable to p:dataTable or any other primefaces component, it works. I am trying to make it work with h:dataTable.
Primefaces 8.0, JSF 2.5
Look on this simple example:
<h:form id="form">
<h:panelGroup id="wrapper" layout="block">
<h:dataTable id="table" border="1" value="#{testBean.list}" var="person">
<h:column>#{person.name}</h:column>
<h:column>#{person.surname}</h:column>
<h:column>
<p:commandButton id="delTagButton" icon="pi pi-trash"
action="#{testBean.remove(person)}" update="table">
</p:commandButton>
</h:column>
</h:dataTable>
</h:panelGroup>
</h:form>
To really find out what is being updated look in browser console.
If you're trying to update="table" nothing happens (like in your code). If you try to update a parent of the table (which is often a case), you will get an error an error:
SEVERE: Error Rendering View[/example.xhtml]
org.primefaces.expression.ComponentNotFoundException: Cannot find component for expression "wrapper" referenced from "form:table:0:delTagButton".
at org.primefaces.expression.SearchExpressionFacade.cannotFindComponent(SearchExpressionFacade.java:677)
So we could try with "older" parent and realize that update="#form" works! OK, so we want to help to find id="table\wrapper" component. Let try clientId update="form:table". Like with update="table" nothing happens. And no error from PF (so the element can be found). This could mean that h:dataTable cannot be properly re-rendered from inside itself (but I don't want to throw stones:-)). This is often a case with e.g. popups in JSF 3rd party component libraries.
In this particular example I'd say, you have to update form:wrapper (adding form: works) or just #form to get it work. With your code it would be the same. Try to update some table parent or the whole form.
All of above is tested in JSF 2.2, with last RF, an old PF and OmniFaces. But I think the same would be the case with newer versions.
BTW. I didn't know there is JSF 2.5 :-)

p:dataTable how prevent f:viewParam being invoked on 1st rowEdit then “tick save” using JSF at XHTML level (not in Java in backing bean)

EDIT: 2017-04-28 The exact same problem (different circumstances/application) is described here: Process f:viewParam only on page load
Primefaces 6.1.RC2
JSF Mojarra 2.3.0
I already have a Java backing-bean based workaround (explained below) for the problem the following behaviour of p:dataTable causes, but I am not very happy with that workaround, and I would like to understand the behavior of p:dataTable row editing better and if possible I would like to find a purely XHTML-level solution to my problem. (BTW I am otherwise very experienced with p:dataTable, which I have used for some very complex applications for some years.)
It is not about an error or bug in p:dataTable, but the way it behaves during row editing causes me a problem in one situation.
The following code examples are completely simplified and adapted for this forum.
I have an entity Element, which has a relationship List<Link> getLinks(), where Link is also an entity.
Element has an editor edit.xhtml.
The aim is to have an composite component links_editor.xhtml that can be embedded in the edit.xhtml.
There is a CDI-compliant #ViewScoped #Named backing bean Manager.
The edit.xhtml relies on an f:viewParam to load an Element for editing:
<f:view>
<f:metadata>
<f:viewParam name="id" value="#{manager.id}"/>
</f:metadata>
</f:view>
Where in the backing bean Manager:
public void setId(Long id) {
if (id != null) {
//load an Element from database for editing by id
And in the links_editor.xhtml:
<cc:implementation>
<div id="#{cc.clientId}">
<p:growl id="testgrowl"/>
<p:dataTable
id="links_table"
editable="true"
var="link"
value="#{cc.attrs.element.links}"
>
<p:ajax
event="rowEdit"
listener="#{cc.attrs.manager.onLinkRowEdit}"
update="#{cc.clientId}:testgrowl"
/>
<p:column headerText="Link title">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{link.name}" />
</f:facet>
<f:facet name="input">
<p:inputText id="name" value="#{link.name}"/>
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Link URL">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{link.urlAsString}" />
</f:facet>
<f:facet name="input">
<p:inputText id="url" value="#{link.urlAsString}"/>
<p:message
for="url"
display="icon"
/>
</f:facet>
</p:cellEditor>
</p:column>
<p:column>
<p:rowEditor />
</p:column>
</p:dataTable>
The row edit listener:
public void onLinkRowEdit(RowEditEvent event) {
Link link = (Link) event.getObject();
try {
checkLink(link); //throws if URL string malformed
JsfUtil.addInfoMessage("DEBUG: Link: "+link);
} catch (LocalUpdateException ex) {
JsfUtil.addErrorMessage(ex.getMessage());
}
}
(where JsfUtil obviously just leverages FacesContext.getCurrentInstance().addMessage(...))
The issue/concern:
If I edit a Link row in the p:dataTable a first time and then use the "tick save" the onLinkRowEdit listener is invoked, but the diagnostics show that the value appear not to have changed. The reason is that this f:viewParam is invoked:
<f:viewParam name="id" value="#{manager.id}"/>
This (via routes not shown in detail) loads the Element entity again from database via setId(Long id), so that in the composite component edit_links.xthml this essentially resets #{cc.attrs.element.links}, so any changes are discarded.
The interesting thing is that if (without reloading the entire #ViewScoped page) one edits the same p:dataTable row a second time that f:viewParam is NOT invoked, and thereafter it works as desired.
A workaround (rather hacky) is to "block" any attempt to reload the Element by id within the view scope backing bean Manager:
public void setId(Long id) {
//HACK/WORKAROUND: prevent reload of Element by id
if (Objects.equals(id, this.id)) {
return;
}
if (id != null) {
//load an Element from database for editing by id
To be clear, I am aware of the usual strategies for using #PostConstruct and/or lazy database fetching in getters of frequently accessed info under JSF in backing beans. And I don't want to abandon here the f:viewParam approach entirely (and it works well for other situations the same Manager bean is also used for).
My interest is specifically about Primefaces p:dataTable:
Q1: Why does p:dataTable need to call the f:viewParam during the 1st row edit then "tick save", when the row information (in this cases element.links) is clearly already available ?
Q2: Why does p:dataTable NOT need to call the f:viewParam during the 2nd row edit then "tick save" ?
Q3: Is there a JSF XHTML-based way of preventing p:dataTable from calling the f:viewParam at all during a rowEdit then "tick save" (including the 1st go) ?
UPDATE: 2017-04-21: There is now a mini test web app for NetBeans 8.2 demonstrating the problem at:
https://github.com/webelcomau/Webel_PrimeFaces_test_p50445_dataTable_fviewParam
Please just download the master ZIP-archive, unzip it, and open it in NetBeans IDE 8.2. You don't need to Git-clone the project. Make sure you have Glassfish-4.1.1 set as the server for the project.
Both the README there and the web app test page itself give precise steps for reproducing the problem (or the behavior that concerns me).
I have invested some effort in analysing this because I use p:dataTable "embedded" in edit forms together with f:viewParam a lot, and I want to understand this matter better, even if it is not an actual problem with p:dataTable.

Setting the ID of an inputfield in dynamic columns Richfaces JSF-1.2 when not rendered

I've got dynamic columns. Some have Inputfields others don't.
Why do I have to set the Id of an Inputfield if I don't want to render it?
<rich:columns value="#{columnBean.columns}" var="column" index="ind" id="#{column.id}">
<f:facet name="header">
<h:inputText id="#{column.inputFilterId}" value="#{otherBean.filterValue[column.filterBy]}" onkeyup="filterKeyUp(event)" onclick="Event.stop(event);" />
</f:facet>
<h:outputText value="#{columnBean.lineItemHandler[line]}" rendered="#{columnBean.curCol[column.id]}"/>
</rich:columns>
I'm using JSF 1.2 and Richfaces 3.3.3 Final
I fixed it, just put a unique Id-Value from my Column Bean.
The better solution is to do this:
https://stackoverflow.com/a/18358949/5146922
THX BalusC

JSF 2: duplicate IDs inside p:dataList

i have a list of billable services per client and i'm trying to build a table where the user can select which ones shall actually be billed:
<p:dataList value="#{billController.billings}" var="billings">
<p:dataTable value='#{billings.billablesDataModel}' var='item' selection="#{billings.toBill}">
<f:facet name="header">
<h:outputText value="#{billings.client.id}" />
</f:facet>
[...]
</p:dataTable>
</p:dataList>
the problem is, that all the dataTables are rendered with the same ID attribute (j_idt9:j_idt13:0:j_idt14) which is automatically assigned by JSF. i'm suspecting this is causing that the selection doesn't work. (the backing bean billings.toBill is not updated/stays empty.)
i was trying to set the ID attribute of the dataTable manually like this:
<p:dataTable id="#{billings.client.id}" ...>
however, i get the following error:
java.lang.IllegalArgumentException: Empty id attribute is not allowed
(#{billings.client.id} is definitely set to the unique client's ID as i get the right output from an h:outputText for debug purposes.)
can you help me fixing this?
i'm using JSF Mojarra 2.1.1 and PrimeFaces 3.2 on a Tomcat 6.
You need to use p:column for content of datalist as documented in user's guide.
What if you loop over billController.billings via ui:repeat and not via p:dataList:
<ui:repeat var="billings" value="#{billController.billings}">
<p:dataTable value="#{billings.billablesDataModel}" var="item" selection="#{billings.toBill}">
[...]
</p:dataTable>
</ui:repeat>

JSF command button attribute is transferred incorrectly

I have following code in jsf page, backed by jsf managed bean
<h:dataTable value="#{poolBean.pools}" var="item">
<h:column>
<f:facet name="header">
<h:outputLabel value="Id"/>
</f:facet>
<h:outputText value="#{item.id}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputLabel value="Start Range"/>
</f:facet>
<h:inputText value="#{item.startRange}" required="true"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="End Range"/>
</f:facet>
<h:inputText value="#{item.endRange}" required="true"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Pool type"/>
</f:facet>
<h:selectOneMenu value="#{item.poolType}" required="true">
<f:selectItems value="#{poolBean.poolTypesMenu}"/>
</h:selectOneMenu>
</h:column>
<h:column>
<f:facet name="header"/>
<h:commandButton id="ModifyPool" actionListener="#{poolBean.updatePool}" image="img/update.gif" title="Modify Pool">
<f:attribute name="pool" value="#{item}"/>
</h:commandButton>
</h:column>
</h:dataTable>
This code fragment is dedicated to editing come collection of items. Each row of the table contains "edit" button that submits changed values of the row to the server. It has the item itself as an attribute. Submit is performed by calling actionListener method in the backing managed bean.
This code runs correctly on Glassfish v 2.1
But when the server was updated to Glassfish v 2.1.1, the attribute stopped to be passed correctly. Instead of passing edited item (when we change the values in table row, we are actually changing the underlying object fields), the source item is submitted to server, i.e. the item that was previously given to the page. All the changes that were made on the page are discarded.
I tried to update jsf version from 1.2_02 to 1.2_14 (we are using jsf RI), but it had no effect.
Perhaps anyone came across the same problem? Any help and suggestions will be appreciated.
Glassfish ships with bundled JSF. Glassfish v2.1.1 ships with Mojarra 1.2_13. You actually don't need to have your own JSF libs in the /WEB-INF/lib. I am not sure how this particular problem is caused, but to start, you need to ensure that you don't have JSF version collisions in the classpath.
That said, the preferred JSF 1.2 way of passing bean properties is using f:setPropertyActionListener.
<h:commandButton id="ModifyPool" actionListener="#{poolBean.updatePool}" image="img/update.gif" title="Modify Pool">
<f:setPropertyActionListener target="#{poolBean.pool}" value="#{item}"/>
</h:commandButton>
Update: I recall something; this problem suggests that you still have a JSF 1.2 version older than 1.2_05 around in the classpath. Handling of component attributes has changed as per this version in favour of performance enhancements. In a nutshell, if you have a jsf-api.jar of older than 1.2_05 in your classpath, while there's a jsf-impl.jar of 1.2_05 or newer in your classpath, you will experience exactly this problem.
The solution is obvious: cleanup your classpath to get rid of the older JSF version. Paths covered by the webapp's default classpath are under each /WEB-INF/lib, Appserver/lib (which is in case of Glassfish somewhere in Appserver/domains/domainname/*) and the JRE/lib and JRE/lib/ext. Keep in mind that Glassfish's javaee.jar includes JSF libraries as well, so you really need to ensure that you don't have that JAR (or any other appserver-specific JAR file) in your /WEB-INF/lib or somewhere else.
You can add JBoss EL and write:
#{poolBean.updatePool(item)}
You don't need the whole Seam for that, works fine with JSF RI.
Probably it has to do with the way JSF 1.2 implements actionListener.
In JSF 1.1 and until recent implementations of JSF 1.2 (Richfaces, Trinidad etc) the order was setPropertyActionListener (or Attribute) -> actionListener -> action.
In JSF 1.2 and now implemented in Richfaces and Trinidad (not sure about IceFaces) the order is actionListener -> setPropertyActionListener (or Attribute) -> action.
I know it is disturbing and very annoying...
Who thought of it? What did they have in mind?
Anyway, try using an action instead of an actionListener and see if it works.

Resources