Primefaces binding datatable with viewscope - jsf

I'm currently building an xhtml page based on Primefaces 3.5 (which I can't update...not lucky this time!).
In this page I need to build dynamically different datatables so I thought that unique way to achieve my task is through the binding method.
So I've made:
<p:dataTable id="bindQTable" var="item"
value="#{bindingHtmlTableClass.items}"
binding="#{bindingHtmlTableClass.dataTable}">
<p:column headerText="Name Column">
<h:outputText value="#{item}" />
</p:column>
<p:column>
<p:commandButton value="remove"
action="#{bindingHtmlTableClass.remove}" />
</p:column>
</p:dataTable>
and the bean:
#ManagedBean(name="bindingHtmlTableClass")
#RequestScoped
public class BindingHtmlTableClass implements Serializable{
private List<String> items;
private DataTable dataTable;
#PostConstruct
private void buildUp(){
System.out.println("postconstruct!");
items = new ArrayList<String>();
items.add("X");
items.add("Y");
}
...getters,setters...
}
The problem now is that I would need to update the tables and especially after a poll period I need to update the values within them.
But i'm in a Request Scope and I can't use a View Scope because of binding.
Is there a better way to implement such thing?
EDIT 4 BalusC: why i need binding the datatable? Because i need to show a datatable linked to a serie of different connection to different installation of RabbitMQ, which is not a known number. My boss asked me to put each RabbitMQ server in a different DataTable where each queue is represented in a different row. Each column needs to show actual queue size plus a button or more to manage the queue (purging, deleting...).
Thanks!

Related

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.

#ViewScoped, f:setPropertyActionListener only works once

I have 2 managedBeans: the first one (RequestScoped) sends a parameter to the second one (ViewScoped) through a h:commandLink. Both managedBeans are in the same page, but I use them in different tabs from a rich:TabPanel:
#ManagedBean
#RequestScoped
public class TheRequestScopedManagedBean {
private String number
...
#ManagedBean
#ViewScoped
public class TheViewScopedManagedBean {
private String number;
...
And here's the view, wich uses a rich:dataTable:
(The action method is only for showing the second tab from a rich:tabPanel).
// ... another dataTable's columns
<rich:column>
<f:facet name="header">Number</f:facet>
<b>
<a4j:commandLink value="#{theRequestScopedManagedBean.number}"
render="someRichPanel" action="#{anotherBean.showSecondTab}" immediate="true">
<f:setPropertyActionListener target="#{theViewScopedManagedBean.number}" value="#{theRequestScopedManagedBean.number}" />
</a4j:commandLink>
</b>
</rich:column>
The problem here is that theViewScopedBean shows the value only the first time, and when I try to pass it again, it shows its default value (null).
I've seen several questions on this website. But I really don't know what to do in this case.
action="#{anotherBean.showSecondTab}" is going to result in a navigation case firing. This will in turn result in the views and request scoped beans being destroyed and recreated (as is the expected behaviour for a view scoped bean).
If you're using EL2.2, you could easily just pass the value directly into a method in the view scoped bean. Let's assume your viewscoped bean has a method takeValue, you can pass the parameter directly into the method as in:
<a4j:commandLink value="#{theRequestScopedManagedBean.number}" render="someRichPanel" action="#{theViewScopedBean.takeValue(theRequestScopedManagedBean.number)}" immediate="true"/>
There are still cleaner ways to transmit data between pages.
Communication in JSF2.0

Creating input fields dynamically in JSF 2.0 and linking it to a backing bean

My requirement is something like this. In a JSF(2.0) page, I have a section called Address. I have added a button which says "Add an Address". When the user clicks the button, new address fields(input text) should be generated dynamically (Line1, Line2, City etc..,). And when I click submit, all the values (Address 1, Address 2 ... Address N) should go to an array list.
So I need to
Dynamically generate UI components on click on a button
Link those UI components to a backing bean (Preferably to a list)
Data tables should not be used for the above
It is very difficult to find proper JSF documentations online, so if anyone can help me out it would be great
Update : The answer posted by noone works good, but I want something more robust, like creating dynamic UI components from the Java Controller (The java bean, using HtmlPanelGrid component). I have been able to create components dynamically using htmlPanelGrid, but I cannot find a way to bind those generated components to the address list in the bean (The one which stores details of all the addresses)
I assume that you have a class Address for the addresses. And a AddressBean with a List to keep the adresses.
The code might look like this (for the most basic scenario I can think of):
<h:form id="addressForm">
<h:commandButton value="Add Address" action="#{addressBean.addAddress()}" immediate="true" execute="#this">
<f:ajax render="addressForm" />
</h:commandButton>
<c:forEach items="#{addressBean.addressList}" var="address">
<h:inputText value="#{address.street}" /><br />
</c:forEach>
<h:commandButton value="Save" action="#{addressBean.persistAddresses}" />
</h:form>
#ManagedBean
#ViewScoped
public class AddressBean {
private List<Address> addressList = new ArrayList<Address>(); // getter+setter
public void addAddress() {
addressList.add(new Address());
}
public void persistAddresses() {
// store the addressList filled with addresses
}
}
public class Address {
private String address; // getter+setter
}
<c:forEach> is taken from the JSTL. It might work with <ui:repeat>, but depending on your actual scenario it might not.

JSF2: action and actionListener

From this answer by BalusC here Differences between action and actionListener, Use actionListener if you want have a hook before the real business action get executed, e.g. to log it, and/or to set an additional property (by <f:setPropertyActionListener>,. However when I decide to write some code to test this, the result is a bit different. Here is my small code
<h:form id="form">
<h:panelGroup id="mygroup">
<p:dataTable id="mytable" value="#{viewBean.foodList}" var="item">
<p:column>
#{item}
</p:column>
<p:column>
<p:commandButton value="delete"
action="#{viewBean.delete}"
update=":form:mygroup">
<f:setPropertyActionListener target="#{viewBean.selectedFood}"
value="#{item}"/>
</p:commandButton>
</p:column>
</p:dataTable>
</h:panelGroup>
</h:form>
Here is my bean
#ManagedBean
#ViewScoped
public class ViewBean {
private List<String> foodList;
private String selectedFood;
#PostConstruct
public void init(){
foodList = new ArrayList<String>();
foodList.add("Pizza");
foodList.add("Pasta");
foodList.add("Hamburger");
}
public void delete(){
foodList.remove(selectedFood);
}
//setter, getter...
}
According to BalusC, actionListener is more suitable here, but my example show otherwise.
The above code work great with action, but if I switch over to actionListener, then it does not quite work. It will take two clicks for me to delete an entry of this table using actionListener, while if I use action, it delete entry every time I click the button. I wonder if any JSF expert out there can help me understand action vs actionListener
Note If I switch to actionListener, my delete method become public void delete(ActionEvent actionEvent)
You're confusing action with actionListener. The actionListener runs always before the action. If there are multiple action listeners, then they run in the same order as they have been registered. That's why it doesn't work as expected when you use actionListener to call the business action and <f:setPropertyActionListener> to set (prepare) a property which is to be used by the business action. This problem was pointed out and fixed in your previous question Is this Primefaces bug or Mojarra/MyFaces bug.
Whatever you have in the delete() method is clearly a business action and should be invoked by action instead. A business action typically invokes an EJB service and if necessary also sets the final result and/or navigates to a different view.
I tried your example with original JSF's tags <h:commandButton> but I also get the same symptom. I believe if you specify actionListener attribute and at the same time, declare another listener with <f:setPropertyActionListener>, the listener in the attribute actionListener will be fired before the other.
UPDATE: I test my assumption with the following code:
Change your delete function to this one:
public void delete(){
this.selectedFood = "Chicken";
//foodList.remove(selectedFood);
}
Add <h:outputText id="food" value="#{viewBean.selectedFood}" /> inside <h:panelGroup id="mygroup">.
You will see that the outputText is always Chicken.

input binding in ui:repeat in jsf

i am using facelets jsf 2.0 with primefaces 3.0.M2 component library.
i am trying to achieve dynamic numbers of rows including iput fields that are filled when a datatable selection occurs.
whenever a selection is made the dynamic rows generated correctly with input fields but after the first selection for following selections dynamic row count changes correctly but the input fields does not update and keeps showing inputs from the first selection.
here is how i iterate list in facelet;
<ui:repeat value="#{goalEntranceBean.selectedCard.parameterList}" var="prmBean" >
<li><h:outputText value="#{prmBean.lookUp.value}"/></li>
<li>
<h:outputText value="Weight:"/>
<p:inputText id="wx" required="true" value="#{prmBean.weight}">
</p:inputText>
<h:outputText value="Percent:"/>
<p:inputText required="true" value="#{prmBean.percent}">
</p:inputText>
</li>
</ui:repeat>
my bean where i get the list of cards and set the selectedCard with rowSelect event in datatable.
#ManagedBean(name = "goalEntranceBean")
#ViewScoped
public class GoalEntranceAction implements Serializable {
private List<ScoreCard> personalCards = new ArrayList<ScoreCard>();
private ScoreCard selectedCard = new ScoreCard();
......
}
when i checked in debug mode i can see the true list but in screen the elements does not change.
This is a common problem (gets asked every couple of days). To make long story short, inputs inside ui:repeat do not work, period.
It is a problem with JSF, a long standing, famous one. Maybe it will be fixed. Maybe not, it seems that no one really cares (I mean - an input? in a... ui:repeat? such crazy scenario!).
A quick-fix is to use a h:dataTable, possibly ungodly abused with css to make it look like a list. A long-fix is to use some iterator from a different library. Primefaces has an element that should work that renders an unordered list.
thanks for your replies. Sorry for forget sharing the solution.
As i mentioned above i have primefaces datatable.
On row selection event i render datatable and want to update the cells of that datatable.
USING p:inputtext easily solved my problem. Now i can change the data on screen and i can see the values after update operation on screen. I don't understand the reason but it works.
<p:dataTable var="orgPrmBean"
value="#{scoreCardOperationsBean.selectedCard.orgParameterList}"
emptyMessage="#{labels.norecord}"
rowKey="#{orgPrmBean.id}"
>
<p:columnGroup type="header">
<p:row>
<p:column headerText="Parameters" colspan="3" style="text-align:left;width:480;"/>
</p:row>
</p:columnGroup>
<p:column style="text-align:left;width:200px;">
<h:outputText value="#{orgPrmBean.info}"/>
</p:column>
<p:column style="text-align:left;width:180px;">
<p:inputText value="#{orgPrmBean.weight}"
rendered="#{scoreCardOperationsBean.selectedCard.goalEdit}">
<f:convertNumber maxFractionDigits="0"/>
</p:inputText>
</p:column>
</p:dataTable>
It IS possible to make it work, but the solution is to bind the inputs to a backing bean, and update the values of the controls in the backing bean via listeners (using the new value received in the argument). Obviously this isn't a good solution if you have a complex form, as you need to add a listener/control in the backing bean for each control in the page, but it's practical if you just have one or two inputs.

Resources