JSF command button attribute is transferred incorrectly - jsf

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.

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 :-)

Filtering issues (no change in contents) in datatable primefaces 3.5, sorting works

Primefaces 3.5 doesn't seem to filter data at all from the datatable, oddly enough it somehow reorders them as I type, so, there must be some AJAX calls firing, but obviously not the right ones.
<h:panelGroup id="table-wrapper-component">
<prime:dataTable
rendered="#{artifactSelectionBackingBean.visibleComps}"
value="#{artifactSelectionBackingBean.components}"
var="tagInfoObject" emptyMessage="No tags found with given criteria"
filteredValue="#{artifactSelectionBackingBean.filteredComponents}">
<prime:ajax event="filter" global="false" />
<prime:column sortBy="#{tagInfoObject.tagId}"
headerText="Identifier" filterMatchMode="contains" filterBy = "#{tagInfoObject.tagId}">
<h:outputText value="#{tagInfoObject.tagId}" />
</prime:column>
<prime:column sortBy="#{tagInfoObject.type.tagTypeId}"
headerText="Tag Identifier" filterMatchMode="contains" filterBy ="#{tagInfoObject.type.tagTypeId}">
<h:outputText value="#{tagInfoObject.type.tagTypeId}" />
</prime:column>
<prime:column sortBy="#{tagInfoObject.title}" headerText="Title" filterMatchMode="contains" filterBy="#{tagInfoObject.title}">
<h:outputText value="#{tagInfoObject.title}" />
</prime:column>
<prime:column filterBy="#{tagInfoObject.description}"
filterMatchMode="contains" sortBy="#{tagInfoObject.description}"
styleClass="wrap" headerText="Component Description">
<h:outputText value="#{tagInfoObject.description}" />
</prime:column>
</prime:dataTable>
</h:panelGroup>
Any help is appreciated! All the Beans and method calls exist and return the appropriate data, just that the filtering doesn't seem to work at all.
Also, note that sorting functions properly only filtering does not!
The issue was that you always need to wrap any filtering/sorting attributes in a data table with an h:form tag. This is not explicitly specified in the documentation of PrimeFaces, however, it is in the showcase here. I wrapped the whole thing in form tags.
So, don't forget to wrap your data tables in a form if you want any type of interaction provided by primefaces.
Your managed Bean Code will do a lot of good
Post your managed bean code.
May be you have not set the value for artifactSelectionBackingBean.filteredComponents in the managed bean

JSF 2.2 #ViewScoped binding bug?

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.

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>

How dynamically generate ace:tabPane components?

I am using JSF 2.1 and ICEFaces 2 and I have a tabset like:
<ace:tabSet clientSide="true">
<ace:tabPane>
<f:facet name="label">My First Tab</f:facet>
<h:outputText value="One"></h:outputText>
</ace:tabPane>
<ace:tabPane>
<f:facet name="label">Second Tab</f:facet>
<h:outputText value="Two"></h:outputText>
</ace:tabPane>
<ace:tabPane>
<f:facet name="label">Third Tab</f:facet>
<h:outputText value="Third"></h:outputText>
</ace:tabPane>
</ace:tabSet>
Instead of hardcoding the tabPanes, I want to generate them dynamically based on a list. How can I achieve this by standard JSF or ICEFaces components?
I tried to use the <ui:repeat>, but it doesn't work:
<ui:repeat var="o" value="#{bean.myList}" varStatus="status">
<ace:tabPane>
<f:facet name="label">#{o.name}</f:facet>
<h:selectManyCheckbox value="#{o.valuesArray}" layout="pageDirection">
<f:selectItems value="#{o.checkboxes}" />
</h:selectManyCheckbox>
</ace:tabPane>
</ui:repeat>
I don't do ICEFaces, but you're encountering basically the same problem as RichFaces has with its <rich:tab>. As there exist no hypothetical <rich:tabs> (like as <rich:columns> which would be the dynamic variant of <rich:column>/<h:column>), one would have to use the view build time JSTL <c:forEach> tag to prepare the JSF view with those tags. You could apply the same on your ICEFaces page:
<ace:tabSet clientSide="true">
<c:forEach items="#{bean.tabs}" var="tab">
<ace:tabPane>
<f:facet name="label">#{tab.label}</f:facet>
<h:outputText value="#{tab.name}"></h:outputText>
</ace:tabPane>
</c:forEach>
</ace:tabSet>
Note that this will only fail if #{bean} is not a real managed bean, but an expression which in turn depends on an evaluation of another JSF component, such as <h:dataTable var="bean">.
The <ui:repeat> won't work as it's a render-time tag. It won't dynamically generate multiple JSF components before the JSF component tree is been built.
See also:
ICEFaces issue 6527 - Dynamically adding/removing ace:tabPane Results in ace:tabset Retrieving Entire Tabset Content
ICEFaces issue 6560 - New ace:tabs dynamic tabset component
i think you can write like this:
<ice:panelTabSet var="tab" value="#{mainTabsTempl.tabs}">
<ice:panelTab label="#{tab.label}">
body
</ice:panelTab>
</ice:panelTabSet>
It's not tabSet tag, but have the same work.

Resources