request scoped dataTable problem with synchronization of dat
ncollette Sep 22, 2008 11:24 AMI have the weirdest thing happening to me in a rich:dataTable. Here's the situation: I have a table of users, and I have an action button to massEnable/massDisable them. So naturally I added a select column on the table so that I could select multiple users. The problem is that when I select them then try to mass enable the users, it acts like I didn't select anyone. After debugging for awhile, I found out what it's doing, but I have no idea how to fix it. If anyone has had similar trouble or knows what I'm doing wrong I would greatly appreciate it. Here's what I found happens: The backing bean is request scoped, the page loads, and let's say 4 user objects are returned with addresses 1-4. Then when the action is performed, a new request scoped backing bean for users is instantiated, and 4 new user objects are fetched from the database with addresses 5-8, then the setSelected methods are called on the "old" user objects addresses 1-4. So naturally when the action method enableUsers is called, it can't find the selected objects, because it checks the newly fetched objects 5-8. any ideas?
Interestingly, if I use h:dataTable or t:dataTable, instead of calling setSelected on 1-4, it correctly calls setSelected on the newly fetched 5-8, and operation is as expected. This is why I'm posting, because it seems to be a bug.
I'm using facelets.
I'm using richFaces 3.2.2, though I've also tried 3.2.1
Here's the .jspx code:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:t="http://myfaces.apache.org/tomahawk"
xmlns:rich="http://richfaces.org/rich" version="2.0">
<ui:composition template="/template.jspx">
<ui:param name="bean" value="#{userBean}" />
<ui:param name="onLoad" value='doOnLoad()' />
<ui:define name="urlTitle">
<ui:insert name="urlTitles">Summary of Users Template</ui:insert>
</ui:define>
<ui:define name="script">
<script type="text/javascript">
/* <![CDATA[ */
function doOnLoad() {
document.getElementById('filterGridForm:userTable:inputBoxForLoginName').focus();
}
function submitMethod (event) {
var keycode;
if (window.event) {
keycode = window.event.keyCode;
} else if (event) {
keycode = event.which;
} else {
return true;
}
if (keycode == 13) {
document.getElementById('filterGridForm:filterSubmitButton').click();
return false;
} else {
return true;
}
}
function hidePopup () {
popup = document.getElementById("78");
if (null != popup) {
var browser=navigator.appName;
var b_version=navigator.appVersion;
var version=parseFloat(b_version);
if ((browser=="Netscape")|| (browser=="Microsoft Internet Explorer" && version>=7))
{
popup.setAttribute("style", "visibility: hidden");
} else {
popup.style.cssText="visibility: hidden; height: 0px; width: 0px;";
}
}
}
function popupClipped(theComponent) {
var closeButton = document.createElement("button");
var browser=navigator.appName;
var b_version=navigator.appVersion;
var version=parseFloat(b_version);
openDiv = document.getElementById("78");
if (openDiv == null)/*it wasn't found*/ {
openDiv = document.createElement("div");
}
openDiv.innerHTML = theComponent.childNodes.item(1).nodeValue + "<br />" + "<br />";
openDiv.setAttribute("id", "78");
if ((browser=="Netscape")|| (browser=="Microsoft Internet Explorer" && version>=7))
{
closeButton.setAttribute("id", "closeButton");;
closeButton.setAttribute("onclick", "hidePopup()");
openDiv.setAttribute("style", "position: absolute; left: 100px; top: 300px; display: table; text-align: center; padding: 20px; background: #ffde00; border: 2px solid #00FF00;");
} else {
closeButton.id="closeButton";
closeButton.attachEvent("onclick",hidePopup);
openDiv.style.cssText="position: absolute; left: 100px; top: 300px; display: table; text-align: center; padding: 20px; background: #ffde00; border: 2px solid #00FF00;";
}
closeButton.innerHTML="close";;
openDiv.appendChild(closeButton);
document.body.appendChild(openDiv);
}
/* ]]> */
</script>
</ui:define>
<!-- menu section -->
<!-- <ui:define name="menu">
<h:form id="menuForm">
<div id="menuContainer"> <ul id="menuSub"> <li>
<h:commandLink id="connection" action="CONNECTION"
value="#{isuite['nav.admin.connection']}" immediate="true">
</h:commandLink> </li> <li> <h:commandLink action="MESSAGES"
id="messages" value="#{isuite['nav.admin.messages']}" immediate="true">
</h:commandLink> </li> <li> <h:commandLink action="LOGS"
id="logs" value="#{isuite['nav.admin.logs']}" immediate="true">
</h:commandLink> </li> <li class="selected"> <h:commandLink action="USERS"
id="users" value="#{isuite['nav.admin.users']}" immediate="true">
</h:commandLink> </li> <li> <h:outputLink id="helpLink" styleClass="last" value="help.jspx"
target="blank">
<f:param name="pageTitleKey" value="title.user.summary" />
<h:outputText id="helpText" value="#{isuite['sub.help']}" />
</h:outputLink> </li> </ul> </div>
</h:form>
</ui:define> -->
<ui:define name="content">
<div id="content">
<div id="container">
<ui:define name="title">
<ui:insert name="titles">
<div id="title">
<h:outputText id="theTitle" value="User Summary" />
</div>
</ui:insert>
</ui:define>
<h:form id="filterGridForm">
<div id="filter">
<table>
<tr>
<td class="filterTitle">
<h:outputLabel styleClass="filterTitle"
id="filterLabel" value="Roles Filter" />
</td>
<td>
<div class="filterCheckBoxesAndButtonsWrapper">
<t:selectManyCheckbox
styleClass="horizontalCheckBoxes" id="roles"
layout="lineDirection" layoutWidth="2"
value="#{userBean.roles}">
<f:selectItems
value="#{userBean.allRoles}" />
</t:selectManyCheckbox>
<h:commandButton id="filterSubmitButton"
value="#{isuite['submit']}"
styleClass="btnWithOurStyle"
action="#{userBean.changeFilterSetting}" />
<h:commandButton id="filterClearButton"
value="#{isuite['reset']}"
styleClass="btnWithOurStyle"
action="#{userBean.resetFilterSetting}" />
</div>
</td>
</tr>
</table>
</div>
<div id="gridContainer">
<h:outputText id="ifThereAreNoUsers"
rendered="#{empty userBean.users}"
value="#{isuite['users.noUsers']}" />
<rich:dataTable id="userTable" rows="10"
value="#{userBean.users}" var="aParticularUser"
rowBandingInterval="1">
<rich:column styleClass="gridFirstColumn selectColumn">
<f:facet name="header" id="selectHeader">
<h:panelGroup>
<div class="gridHeaderTitle">
<h:outputText value="#{isuite['select']}" />
</div>
<div class="gridSpaceWhereFilterDoesNotExist">
<h:inputText disabled="true"
class="gridSpacingHiddenInput" />
</div>
</h:panelGroup>
</f:facet>
<h:selectBooleanCheckbox id="userSelected"
value="#{aParticularUser.selected}" />
</rich:column>
<rich:column styleClass="editColumn">
<f:facet name="header" id="editHeader">
<h:panelGroup>
<div class="gridHeaderTitle">
<h:outputText value="#{isuite['edit']}" />
</div>
<div class="gridSpaceWhereFilterDoesNotExist">
<h:inputText disabled="true"
class="gridSpacingHiddenInput" />
</div>
</h:panelGroup>
</f:facet>
<h:commandButton id="userEditButton" value=""
action="#{userBean.editThese}"
styleClass="buttonEditImage">
<f:setPropertyActionListener
target="#{userBean.theUser}"
value="#{aParticularUser}" />
</h:commandButton>
</rich:column>
<rich:column>
<f:facet name="header" id="loginNameHeader">
<h:panelGroup>
<div class="gridHeaderTitle">
<h:outputText
value="#{isuite['user.loginName']}" />
</div>
<div class="gridFilter">
<h:inputText id="inputBoxForLoginName"
onkeypress="submitMethod(event)"
value="#{userBean.userFilter.loginName}" />
</div>
</h:panelGroup>
</f:facet>
<div class="gridDataClipperWrapper">
<h:outputText value="#{aParticularUser.loginName}" />
</div>
</rich:column>
<rich:column>
<f:facet name="header" id="firstNameHeader">
<h:panelGroup>
<div class="gridHeaderTitle">
<h:outputText
value="#{isuite['user.firstName']}" />
</div>
<div class="gridFilter">
<h:inputText id="inputBoxForFirstName"
onkeypress="submitMethod(event)"
value="#{userBean.userFilter.firstName}" />
</div>
</h:panelGroup>
</f:facet>
<div class="gridDataClipperWrapper">
<h:outputText value="#{aParticularUser.firstName}" />
</div>
</rich:column>
<rich:column>
<f:facet name="header" id="lastNameHeader">
<h:panelGroup>
<div class="gridHeaderTitle">
<h:outputText
value="#{isuite['user.lastName']}" />
</div>
<div class="gridFilter">
<h:inputText id="inputBoxForLastName"
onkeypress="submitMethod(event)"
value="#{userBean.userFilter.lastName}" />
</div>
</h:panelGroup>
</f:facet>
<div class="gridDataClipperWrapper">
<h:outputText value="#{aParticularUser.lastName}" />
</div>
</rich:column>
<rich:column>
<f:facet name="header" id="userRolesForGrid">
<h:panelGroup>
<div class="gridHeaderTitle">
<h:outputText
value="#{isuite['user.roles']}" />
</div>
<div class="gridSpaceWhereFilterDoesNotExist">
<h:inputText disabled="true"
class="gridSpacingHiddenInput" />
</div>
</h:panelGroup>
</f:facet>
<div class="gridDataClipperWrapper">
<h:outputText value="#{aParticularUser.roles}">
<f:converter converterId="roleConverter" />
</h:outputText>
</div>
</rich:column>
<rich:column>
<f:facet name="header" id="enabledHeader">
<h:panelGroup>
<div class="gridHeaderTitle">
<h:outputText
value="#{isuite['user.enabled']}" />
</div>
<div class="gridFilter">
<h:inputText id="filterEnabled"
maxlength="5"
onkeypress="submitMethod(event)"
value="#{userBean.userFilter.enabled}"
converter="booleanConverter" />
</div>
</h:panelGroup>
</f:facet>
<h:outputText value="#{aParticularUser.enabled}" />
</rich:column>
</rich:dataTable>
<ui:insert name="buttonsOfFunctionality">
<h:commandButton id="addNewUser"
value="#{isuite['user.add']}"
styleClass="btnWithOurStyle"
action="#{userBean.addNewUser}">
</h:commandButton>
<h:commandButton id="enableUsers"
value="#{isuite['user.enableUsers']}"
styleClass="btnWithOurStyle"
action="#{userBean.enableUsers}">
</h:commandButton>
<h:commandButton id="disableUsers"
value="#{isuite['user.disableUsers']}"
styleClass="btnWithOurStyle"
action="#{userBean.disableUsers}">
</h:commandButton>
<h:commandButton id="export" value="#{isuite['export']}"
rendered="#{! empty userBean.users}"
styleClass="btnWithOurStyle"
action="#{userBean.exportUsers}"
title="#{isuite['export']}" />
<t:inputFileUpload id="userFileUpload"
value="#{userBean.file}" storage="file" />
<h:commandButton id="import" value="#{isuite['import']}"
styleClass="btnWithOurStyle"
action="#{userBean.importUsers}"
title="#{isuite['import']}" />
</ui:insert>
</div>
</h:form>
<div style="" />
</div>
</div>
</ui:define>
</ui:composition>
</jsp:root>