Primefaces InputText passing empty value to the backing bean - jsf

I am using JSF template with top, left and content views of a chat application. On the left is a list of discussions, displayed using composite components. When I select one discussion, every conversation in the selected discussion is required to the displayed in the content. There is a create button in the content pane which allows to create a new text within the selected discussion. On click of create, a dialog opens to input the message text.
The issue is, when I select a discussion on the left, and then click on the create in the content, the text message from the dialog is passing blank values to the backing bean. The setter method is getting called, but the value passed is blank. I observed that, if I click on create when the page is loaded, without selecting a discussion, it is sending the message with correct value. Every subsequent creates even after selecting a discussion continues to pass the same value.
I am using Primefaces 3.4.2 and glassfish 4.
Below is the center pane xhtml
<h:body>
<h:form id="newForm">
<p:commandLink id="test" value="Create Bubble" />
<p:overlayPanel id="panel" for="test" >
<p:commandButton id="map" icon="ui-icon-map" onclick="map_dlg.show();"/>
<p:commandButton id="map1" icon="ui-icon-document" onclick="survey_dlgcreate.show();"/>
<p:commandButton id="map2" icon="ui-icon-folder" onclick="txt_dlg.show();"/>
</p:overlayPanel>
<a:discussionComp discussion="#{displayDiscussionBean}"/>
</h:form>
<p:focus id="focus" context="textdlg"/>
<p:dialog id="textdlg" modal="true" header="Text bubble" appendToBody="true" hideEffect="fade" widgetVar="txt_dlg">
<h:form id="t3">
<p:outputLabel value="Enter your message"/><p:inputText value="#{displayDiscussionBean.txtMsg}"/>
<p:commandButton icon="Post" action="#{displayDiscussionBean.createTextBubble()}" oncomplete="txt_dlg.hide();"/>
</h:form>
</p:dialog>
</h:body>
Here is what my left panel is.
<!--IMPLEMENTATION-->
<cc:implementation>
<h:form id="leftPanel">
<p:dataTable id="disc" value="#{cc.attrs.discussionModel}" var="discussion" style="margin-top: 2px;height: 100%" selectionMode="single" selection="#{discussionBean.selectedDiscussion}" >
<p:ajax event="rowSelect" update=":detail_panel" />
<f:facet name="header">
Discussions
<h:commandLink action="#{discussionBean.createDiscussion()}">
<p:graphicImage id="add" url="/resources/images/plus.png" style="height: 25px;float: right" />
<p:tooltip for="add" value="Add Discussion" style="font-size: 12px" hideEffect="fade"/>
</h:commandLink>
</f:facet>
<p:column style="font-size: 12px;">
#{discussion.title}
</p:column>
</p:dataTable>
</h:form>
</cc:implementation>
My backing bean (displayDiscussionBean) for the create is a SessionScoped bean, and has get and set methods for the txtMsg. However on submit, set method gets fired, but with blank value. Below is the backing bean.
#Named
#SessionScoped
public class DisplayDiscussionBean implements Serializable {
private static final long serialVersionUID = 1L;
#EJB
private DiscussionEJB discussionEJB;
private TextEJB textEJB;
private DiscussionEntity de;
private HashMap<Integer, TextEntity> textMap;
private String selectedOption;
#Inject
private DiscussionBean discussionBean;
private String msg;
private Integer currentBubbleId;
private Integer currentBubbleType = 55;
#Inject
private Locations loc;
private String txtMsg;
private TreeNode root;
private Integer did;
public Integer getDid() {
return did;
}
public void setDid(Integer did) {
this.did = did;
setDetails();
}
public DisplayDiscussionBean() {
}
public DisplayDiscussionBean(Integer id) {
}
private void setDetails() {
de = discussionEJB.getDiscussionDetails(did);
textMap = new HashMap<>();
root = new DefaultTreeNode("Root", null);
Map<Integer, TreeNode> nodeMap = new HashMap<>();
for (BubbleEntity b : de.getBubbleList()) {
TreeNode node = new DefaultTreeNode(b, null);
nodeMap.put(b.getBubbleId(), node);
TextEntity te = (TextEntity) b;
textMap.put(te.getBubbleId(), te);
}
for (BubbleEntity b : de.getBubbleList()) {
if (b.getParentId() != null) {
TreeNode currNode = nodeMap.get(b.getBubbleId());
TreeNode parentNode = nodeMap.get(b.getParentId());
currNode.setParent(parentNode);
} else {
TreeNode currNode = nodeMap.get(b.getBubbleId());
currNode.setParent(root);
}
}
}
public void createTextBubble() {
if (did == null){
did=discussionBean.getSelectedDiscussion().getDiscussionId();
}
textEJB.createTextBubble(txtMsg, did, null);
}
public DiscussionEntity getDe() {
return de;
}
public void setDe(DiscussionEntity de) {
this.de = de;
}
public TreeNode getRoot() {
return root;
}
public void setRoot(TreeNode root) {
this.root = root;
}
public HashMap<Integer, TextEntity> getTextMap() {
return textMap;
}
public void setTextMap(HashMap<Integer, TextEntity> textMap) {
this.textMap = textMap;
}
public String getSelectedOption() {
return selectedOption;
}
public void setSelectedOption(String selectedOption) {
this.selectedOption = selectedOption;
}
public Integer getCurrentBubbleId() {
return currentBubbleId;
}
public void setCurrentBubbleId(Integer currentBubbleId) {
this.currentBubbleId = currentBubbleId;
}
public Integer getCurrentBubbleType() {
return currentBubbleType;
}
public void setCurrentBubbleType(Integer currentBubbleType) {
this.currentBubbleType = currentBubbleType;
}
public String getTxtMsg() {
return txtMsg;
}
public void setTxtMsg(String txtMsg) {
this.txtMsg = txtMsg;
System.out.println("set text msg is "+txtMsg);
}
}
Any suggestioins what am I doing wrong here?

Try using only one form instead. Remove the inner form. I too had a similar issue and removing inner form worked for me.
If that doesn't work try adding 'process' or 'execute' attribute to your button which calls your bean method

Related

Using P:CommandButton in PrimeFaces

Originally I have this form for user input and do a search.
<h:form id="wordForm">
<h:panelGrid columns="4">
<h:inputText id="word" "
value="#{wordController.word}" />
<h:message for="word" />
<h:commandButton id="search" value="search"
action="#{wordController.search}" />
</h:panelGrid>
</h:form>
Now I want to use PrimeFaces for autocomplete feature, and this is my new form with Autocomplete. How can I replace the new form with the above form?
<h:form>
<p:growl id="msgs" showDetail="true" />
<h:panelGrid columns="2" cellpadding="5">
<p:autoComplete id="wordForm" value="#{autoCompleteView.query}"
completeMethod="#{autoCompleteView.completeQuery}" var="query"
itemLabel="#{query.displayName}" itemValue="#{query}"
converter="queryConverter" forceSelection="true" />
<p:commandButton value="search" oncomplete="PF('dlg').show()" **action="#{wordController.search}"** />
</h:panelGrid>
</h:form>
More specifically, I think I still need to somehow use "action="#{wordController.search}" in P:CommandAction button so that I don't need to change anything else in backend. But How do I pass the query parameter to the "wordController.word" variable? Because now "action="#autoCompleteView.query" takes the user input.
How can I modify this without significant change to current bean code? Do I have to unify the original search bean WordController with the new AutocompleteView bean? because now the user input is accepted into AutoCompleteView bean.
AutoCompleteView.java
#ManagedBean
public class AutoCompleteView {
private Query query;
#ManagedProperty("#{queryService}")
private QueryService service;
private List<Query> selectedQueries;
public List<Query> completeQuery(String query) {
System.out.println(query);
List<Query> allQueries = service.getQueries();
List<Query> filteredQueries = new ArrayList<Query>();
for (int i = 0; i < allQueries.size(); i++) {
Query skin = allQueries.get(i);
if(skin.getName().toLowerCase().contains(query)) {
filteredQueries.add(skin);
}
}
return filteredQueries;
}
public void onItemSelect(SelectEvent event) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Item Selected", event.getObject().toString()));
}
public Query getQuery() {
return query;
}
public void setQuery(Query query) {
this.query = query;
}
public void setService(QueryService service) {
this.service = service;
}
public List<Query> getSelectedQueries() {
return selectedQueries;
}
public void setSelectedQueries(List<Query> selectedQueries) {
this.selectedQueries = selectedQueries;
}
}
Edited per suggestion:
#Named
#RequestScoped
public class WordController {
private String word;
// For AutoComplete suggestions
private Query selectedQuery;
#Inject
private QueryService service;
#Inject
private Word wordObject;
public void search() {
if (word != null && !word.isEmpty()) {
wordObject.searchWord(word);;
...
}else {
System.out.println("Query can't be null!");
}
}
public List<Query> completeQuery(String query) {
List<Query> allQueries = service.getQueries();
List<Query> filteredQueries = new ArrayList<Query>();
for (int i = 0; i < allQueries.size(); i++) {
Query skin = allQueries.get(i);
if(skin.getName().toLowerCase().contains(query)) {
filteredQueries.add(skin);
}
}
return filteredQueries;
}
public String getWord() {
return word;
}
public void setWord(String word) {
this.word = word;
}
public Query getSelectedQuery() {
return selectedQuery;
}
public void setSelectedQuery(Query selectedQuery) {
this.selectedQuery = selectedQuery;
}
}
Question: Originally, my 'word' is filled through an "h:inputText" in JSF view and search() is called in JSF:
<h:commandButton id="search" value="Search!" action="#{wordController.search}" />
Now, how do I get "selectedQuery" from completeQuery() method, and then use it to fill "word" and then call search() method?

datamodel must implement when selection is enabled.?

I wanted to remove rows from the data table when the checkbox is ticked and remove button is pressed..
This is the datatable snippet :
<p:dataTable id="cartTable" lazy="true" scrollable="true"
scrollHeight="115" selection="#{Cart_Check.selectedItems}"
value="#{Cart_Check.cart}" var="cart" rowKey="#{cart.sheetno}"
style="widht:100%;margin-top:10%;margin-left:1%;margin-right:30px ;box-shadow: 10px 10px 25px #888888;">
<f:facet name="header">
Checkbox Based Selection
</f:facet>
<p:column selectionMode="multiple" style="width:2%">
</p:column>
//Here the columns are metion
<f:facet name="footer">
<p:commandButton id="viewButton" value="Remove" />
</f:facet>
</p:dataTable>
This is the backing bean
public class checkcart {
private int items;
private ArrayList<User_Cart> cart;
private ArrayList<User_Cart> selectedItems;
public checkcart() {
getvalues();
}
//getter and setter
public void getvalues() {
FacesContext context = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession) context.getExternalContext()
.getSession(false);
System.out.println("Cart Request ::::" + session.getAttribute("regid"));
try {
Connection connection = BO_Connector.getConnection();
String sql = "Select * from cart_orderinfo where usrregno=?";
PreparedStatement ps = connection.prepareStatement(sql);
ps.setString(1, (String) session.getAttribute("regid"));
ResultSet rs = ps.executeQuery();
cart = new ArrayList<>();
while (rs.next()) {
User_Cart user_cart = new User_Cart();
user_cart.setSheetno(rs.getString("sheetno"));
user_cart.setState_cd(rs.getString("state_cd"));
user_cart.setDist_cd(rs.getString("dist_cd"));
user_cart.setLicensetype(rs.getString("license_type"));
user_cart.setFormat(rs.getString("sheet_format"));
user_cart.setQuantity(rs.getInt("quantity"));
cart.add(user_cart);
}
} catch (Exception ex) {
System.out.println(ex);
}
}
}
and when i run this page i get the following error
datamodel must implement org.primefaces.model.selectabledatamodel when selection is enabled.
But when i remove the checkbox then their is no error but it is without a checkbox.
What to do and how to resolve the following error ..Kindly help..
I want something like this :
http://www.primefaces.org/showcase/ui/datatableRowSelectionRadioCheckbox.jsf
You just need to define ListDataModel as shown below,
public class SD_User_Cart extends ListDataModel<User_Cart> implements SelectableDataModel<User_Cart> {
public SD_User_Cart() {
}
public SD_User_Cart(List<User_Cart> data) {
super(data);
}
#Override
public User_Cart getRowData(String rowKey) {
//In a real app, a more efficient way like a query by rowKey should be implemented to deal with huge data
List<User_Cart> rows = (List<User_Cart>) getWrappedData();
for (User_Cart row : rows) {
if (row.getCartId.toString().equals(rowKey)) {//CartId is the primary key of your User_Cart
return row;
}
}
return null;
}
#Override
public Object getRowKey(User_Cart row) {
return row.get.getCartId();
}
}
Change your "cart" object into SD_User_Cart as shown below,
private SD_User_Cart cart;
Then define selection in p:datatable, and add a column as shown below,
<p:column selectionMode="multiple" style="width:18px"/>
Hope this helps:)
You need to define a your private ArrayList<User_Cart> selectedItems; data member in back class public class checkcart like this private User_Cart[] selectedItems; and give setter and getter method for the same it will work.
I had also faced same problem.

Losing checked info in p:datatable while changing page

I know this is not a bug.
But i need a suggestion, what can i do not to lose checked knowledge of checked lines?
On JSF page:
<h:form prependId="false" id="searchUserFormTable" >
<p:dataTable id="selectUserTable" var="user"
value="#{userListController.lazyDataModel}" paginator="true"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rows="2" paginatorPosition="bottom" rowKey="#{user}"
lazy="true"
rowsPerPageTemplate="2,10,20,30,40,50"
rendered="#{userListController.lazyDataModel != null}" selection="#{systemMessageEditController.receiverList}"
scrollable="true" scrollHeight="250" resizableColumns="false" >
<p:column selectionMode="multiple" width="18" />
<f:facet name="header">
<h:outputText value=" Users (#{userListController.lazyDataModel.rowCount})" />
</f:facet>
<p:column filterBy="#{user.name}" headerText="Name" filterMatchMode="contains" width="80">
#{user.name}
</p:column>
<p:column filterBy="#{user.surname}" headerText="Surname" filterMatchMode="contains" width="80">
#{user.surname}
</p:column>
<p:column headerText="Gender" width="80">
#{user.gender}
</p:column>
<p:column headerText="City" width="80">
#{user.address.city.name}
</p:column>
<p:column headerText="Status" width="80">
#{user.userStatus}
</p:column>
<p:column headerText="User Detail" width="80">
<h:link value="User Detail" outcome="/view/admin/usermanagement/userInfo.jsf">
<f:param name="userId" value="#{user.id}" />
</h:link>
</p:column>
</p:dataTable>
<p:commandButton value="Tamam" oncomplete="userListDlg.hide();" update=":newMessageForm"></p:commandButton>
</h:form>
All the controller:
#ManagedBean(name="systemMessageEditController")
#ViewScoped
public class SystemMessageEditController {
#ManagedProperty(value = "#{systemMessageService}")
SystemMessageService systemMessageService;
#ManagedProperty(value = "#{securityBean}")
SecurityBean securityBean;
#ManagedProperty(value = "#{systemMessageReceiverService}")
SystemMessageReceiverService systemMessageReceiverService;
#ManagedProperty(value = "#{systemMessageAnswerService}")
SystemMessageAnswerService systemMessageAnswerService;
private SystemMessage systemMessage = new SystemMessage();
private SystemMessageAnswer systemMessageAnswer = new SystemMessageAnswer();
private SystemMessageReceiver systemMessageReceiver = new SystemMessageReceiver();
private User[] receiverList;
private boolean dummy;
public void prepareToEdit(){
systemMessage = systemMessageService.findById(systemMessage.getId());
}
public void prepareToSendMessage(){
systemMessage = new SystemMessage();
receiverList = null ;
}
public void sendMessage(){
if(Util.isNotNull(systemMessage.getTitle())){
boolean success = false;
systemMessageAnswer.setUser(securityBean.getUser());
systemMessage.getSystemMessageAnswerList().add(systemMessageAnswer);
systemMessage.setUserSender(securityBean.getUser());
systemMessageAnswer.setSystemMessage(systemMessage);
if(!systemMessage.isSendAll()){
addMessageReceiver();
}
systemMessage = systemMessageService.save(systemMessage);
systemMessageAnswer = new SystemMessageAnswer();
success = true;
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, FacesUtils.getMessageByKey("systemmessage.send.success"), FacesUtils.getMessageByKey("systemmessage.send.success"));
FacesContext.getCurrentInstance().addMessage("", message);
RequestContext context = RequestContext.getCurrentInstance();
context.addCallbackParam("success", success);
}
else{
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, FacesUtils.getMessageByKey("systemmessage.null.title"), FacesUtils.getMessageByKey("systemmessage.null.title"));
FacesContext.getCurrentInstance().addMessage("", message);
}
}
public void setRead(SystemMessage message){
message.setReaded(true);
systemMessageService.save(message);
}
public void addMessageReceiver(){
for(User user : receiverList){
SystemMessageReceiver messageReceiver = new SystemMessageReceiver();
messageReceiver.setReceiver(user);
messageReceiver.setSystemMessage(systemMessage);
messageReceiver.setReaded(false);
systemMessage.getSystemMessageReceiverList().add(messageReceiver);
}
}
public void deleteMessage(){
boolean success = false;
systemMessageService.delete(systemMessageService.findById(systemMessage.getId()));
success = true;
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, FacesUtils.getMessageByKey("systemmessage.delete.success"), FacesUtils.getMessageByKey("systemmessage.delete.success"));
FacesContext.getCurrentInstance().addMessage("", message);
RequestContext context = RequestContext.getCurrentInstance();
context.addCallbackParam("success", success);
}
public void sendMessageAnswer(){
systemMessageAnswer.setUser(securityBean.getUser());
systemMessageAnswer.setSystemMessage(systemMessage);
systemMessageAnswerService.save(systemMessageAnswer);
if(!systemMessage.isSendAll()){
systemMessage.setSystemMessageReceiverList(systemMessageService.getReceiverListOfMessage(systemMessage));
for(SystemMessageReceiver systemMessageReceiver : systemMessage.getSystemMessageReceiverList()){
if(!systemMessageReceiver.getReceiver().getId().equals(securityBean.getUser().getId())){
systemMessageReceiver.setReaded(false);
systemMessageReceiver.setShowed(false);
systemMessageReceiverService.save(systemMessageReceiver);
}
}
}
systemMessage.getSystemMessageAnswerList().add(systemMessageAnswer);
systemMessageAnswer = new SystemMessageAnswer();
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, FacesUtils.getMessageByKey("systemmessage.send.success"), FacesUtils.getMessageByKey("systemmessage.send.success"));
FacesContext.getCurrentInstance().addMessage("", message);
RequestContext context = RequestContext.getCurrentInstance();
context.addCallbackParam("success", true);
}
public SystemMessageService getSystemMessageService() {
return systemMessageService;
}
public void setSystemMessageService(SystemMessageService systemMessageService) {
this.systemMessageService = systemMessageService;
}
public SystemMessage getSystemMessage() {
return systemMessage;
}
public void setSystemMessage(SystemMessage systemMessage) {
ArrayList<String> fetchedAttributes = new ArrayList<String>();
fetchedAttributes.add("systemMessageAnswerList");
this.systemMessage = systemMessageService.loadWithFetchedAttributes(systemMessage.getId(),fetchedAttributes);
}
public SystemMessageAnswer getSystemMessageAnswer() {
return systemMessageAnswer;
}
public void setSystemMessageAnswer(SystemMessageAnswer systemMessageAnswer) {
this.systemMessageAnswer = systemMessageAnswer;
}
public SecurityBean getSecurityBean() {
return securityBean;
}
public void setSecurityBean(SecurityBean securityBean) {
this.securityBean = securityBean;
}
public SystemMessageReceiverService getSystemMessageReceiverService() {
return systemMessageReceiverService;
}
public void setSystemMessageReceiverService(
SystemMessageReceiverService systemMessageReceiverService) {
this.systemMessageReceiverService = systemMessageReceiverService;
}
public SystemMessageAnswerService getSystemMessageAnswerService() {
return systemMessageAnswerService;
}
public void setSystemMessageAnswerService(
SystemMessageAnswerService systemMessageAnswerService) {
this.systemMessageAnswerService = systemMessageAnswerService;
}
public SystemMessageReceiver getSystemMessageReceiver() {
return systemMessageReceiver;
}
public void setSystemMessageReceiver(SystemMessageReceiver systemMessageReceiver) {
this.systemMessageReceiver = systemMessageReceiver;
}
public User[] getReceiverList() {
return receiverList;
}
public void setReceiverList(User[] receiverList) {
this.receiverList = receiverList;
}
I am losing checked info while jumping one pagination number to another, when i checked some rows, then jump another pagination number in datatable, and go back to old pagination number i loose the checked info, i see nothing has changed.
This is how #ViewScoped works. See the following answer from BalusC:
A view scoped bean lives as long as you interact with the same view (i.e. you return void or null in bean action method). When you navigate away to another view, e.g. by clicking a link or by returning a different action outcome, then the view scoped bean will be trashed by end of render response and not be available in the next request.
which explains that in cases like yours (I just read in one of your comment that you jump to another page before you lose the selection, you should note that in your question too!) the bean is destroyed, so when you navigate back to your dataTable view it gets reconstructed again. This is the reason why receiverList is empty => no selection.
If you want to save your data while navigating between different views, use a bean with scope wider than #ViewScoped, or simply save the selection to a table in your DB.
EDIT
The problem could be in your rowKey attribute. In the current code it points to the user object, in this case make sure that this objects has proper hashCode, equals and toString implementations. If the user class actually has a key or something, it would be easier to change rowKey to rowKey="#{user.id}".
Check the Showcase. I think it works just like you want.
You are probably sending the data via ajax request you should make sure that it process dataTable itself

DataModel must implement org.primefaces.model.SelectableDataModel when selection is enabled.

I'm trying to create a DataTable with Multiple Row Selection but i'm getting an error here's the link of the tutorial http://www.primefaces.org/showcase/ui/datatableRowSelectionMultiple.jsf :
Here's my xhtml:
<p:dataTable border="1" value="#{projectAdminisrationMB.projectNoUsersList}"
var="userObj"
selection="#
{projectAdminisrationMB.selectedUsers}"
selectionMode="multiple" rowIndexVar="rowIndex"binding="#{table2}">
<p:column id="column3">
<f:facet name="header">
<h:outputText value=" user "></h:outputText>
</f:facet>
<h:outputText value="#{userObj.name}"/>
/
<h:outputText value="#{userObj.lastName}"></h:outputText>
<h:outputText value="#{userObj.firstName}"></h:outputText>
</p:column>
<f:facet name="footer">
<p:commandButton id="addProjectUser" value=" Add " onclick="dlg1.show()" />
<p:commandButton id="deleteProjectUser" value=" Delete " />
</f:facet>
</p:dataTable>
Managed Bean :
#ManagedBean
#SessionScoped
public class ProjectAdminisrationMB implements Serializable {
private static final long serialVersionUID = 1L;
private String projectName;
private List <User> projectUsersList;
private List<User> projectNoUsersList;
private List<User> selectedUsers;
private String projectAdmin;
public ProjectAdminisrationMB() {
super();
AdministrationProjectFinal administrationProjectFinal =new
AdministrationProjectFinal();
this.projectUsersList=administrationProjectFinal.getUserList();
this.projectNoUsersList=administrationProjectFinal.getNotUserList();
}
public String getProjectName() {
return projectName;
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
public List<User> getProjectUsersList() {
return projectUsersList;
}
public void setProjectUsersList(List<User> projectUsersList) {
this.projectUsersList = projectUsersList;
}
public String getProjectAdmin() {
return projectAdmin;
}
public void setProjectAdmin(String projectAdmin) {
this.projectAdmin = projectAdmin;
}
public List<User> getProjectNoUsersList() {
return projectNoUsersList;
}
public void setProjectNoUsersList(List<User> projectNoUsersList) {
this.projectNoUsersList = projectNoUsersList;
}
public List<User> getSelectedUsers() {
return selectedUsers;
}
public void setSelectedUsers(List<User> selectedUsers) {
this.selectedUsers = selectedUsers;
}
}
i'm getting this error:
javax.faces.FacesException: DataModel must implement
org.primefaces.model.SelectableDataModel when selection is enabled.....
just add this attribute rowKey to the datatable tag :
<p:dataTable border="1" value="#{projectAdminisrationMB.projectNoUsersList}"
var="userObj"
rowKey="#{userObj.name}"selection="#{projectAdminisrationMB.selectedUsers}"
selectionMode="multiple" rowIndexVar="rowIndex"
binding="#{table2}">
You can get this error if you try to add a new item to the underlying list and forget to assign a value to that new item's rowKey.
Alternatively to rowKey you can wrap your data in a custom model which really implements org.primefaces.model.SelectableDataModel. This is helpful if
all of your your classes have the same kind of #Id (e.g. a long) and can implement the same interface (e.g. EjbWithId)
you want to add additional functionalities to your data which are not domain specific and don't belong e.g. User.
The interface may be something like this:
public interface EjbWithId
{
public long getId();
public void setId(long id);
}
Then a generic implementation of SelectableDataModel for all your classes can be used:
public class PrimefacesEjbIdDataModel <T extends EjbWithId>
extends ListDataModel<T> implements SelectableDataModel<T>
{
public PrimefacesEjbIdDataModel(List<T> data)
{
super(data);
}
#Override public T getRowData(String rowKey)
{
List<T> list = (List<T>) getWrappedData();
for(T ejb : list)
{
if(ejb.getId()==(new Integer(rowKey))){return ejb;}
}
return null;
}
#Override public Object getRowKey(T item) {return item.getId();}
}
In your #ManagedBean:
private PrimefacesEjbIdDataModel<User> dmUser; //+getter
dmUser = new PrimefacesEjbIdDataModel<User>(administrationProjectFinal.getUserList());
first check whether you've added
rowKey="#{userObj.id}"
then you need to have the data table List set in filteredValue attribute of your data table in xhtml, instead of value.

JSF UIRepeat and PostBack

I have a simple page where a I use <ui:repeat> and it gets the value from a backing bean.
The initial request will give it an empty list. The postback then will invoke an action that will change the model behind the <ui:repeat> but it is not rendered?!
I debugged through it and I saw that the <ui:repeat> evaluates the value at restore view phase but thats it. When it reaches render response it does not use the latest value from my bean. Is that the expected behavior?
How can I make that work? Do I have to write my own repeat tag?
I can't really tell what could be the problem without some of your code, but these are the basics:
Backing bean:
public class ObjectService{
private DataModel objectDataModel;
private List<Object> objectList;
private Pagination paginationHelper;
private ObjectDao objectDao = new ObjectDao();
private String queryOption;
public void setQueryOption(String queryOption){
this.queryOption = queryOption;
}
public String getQueryOption(){
return this.queryOption;
}
public <E> PaginationHelper getPagination(final List<E> list) {
pagination = new PaginationHelper(10) {
#Override
public int getItemsCount() {
return list.size();
}
#Override
public DataModel createPageDataModel() {
return new ListDataModel(list);
}
};
return pagination;
}
public void setPagination(PaginationHelper pagination) {
this.pagination = pagination;
}
public List<Object> getObjectList(){
this.objectList = objectDao.readObjectsWhere(queryOption);
return this.objectList;
}
public void setObjectList(List<Object> objectList){
this.objectList = objectList;
}
public DataModel getObjectDataModel(){
if (objectDataModel == null) {
objectDataModel = getPagination(getObjectList()).createPageDataModel();
}
return objectDataModel;
}
public void setObjectDataModel(DataModel objectDataModel){
this.objectDataModel = objectDataModel
}
public String changeModel(){
objectDataModel = null;
return null;
}
}
XHTML page:
...
<h:form>
<fieldset>
<label>
<span>Option:</span>
<h:inputText value="#{objectService.queryOption}" />
</label>
<h:commandButton action="#{objectService.changeModel}" value="request data" />
</fieldset>
<ui:repeat value="#{objectService.objectDataModel}" var="objectVar">
<h:outputLabel value="#{objectVar.property1}" />
<h:outputLabel value="#{objectVar.property2}" />
<h:outputLabel value="#{objectVar.property3}" />
</ui:repeat>
</h:form>
...

Resources