Simple p:inputText in p:dialog not setting value in #Named Bean - primefaces

I am using primefaces 5.1 and still facing problem with p:dialog and p:inputText within that dialog.
Here is the .xhtml content
<ui:define name="content">
<f:metadata> <f:viewAction action="#{vLoginController.initSetup}" /> </f:metadata>
<h:form id="vhome" prependId="false">
<table>
<tr>
<td>
<p:commandButton value="Place Order" action="#{vLoginController.placeOrderHomePage}"
update="logindialog, signupdialog"/>
</td>
</tr>
</table>
<p:dialog id="logindialog" header="Login / Sign up" visible="#{vLoginController.loginDialog}"
draggable="false" resizable="false" modal="true">
<p:messages autoUpdate="true"/>
<h:panelGrid columns="2" cellpadding="5">
<h:outputLabel for="inuserid" value="EmailID:" />
<p:inputText id="inuserid" size="40" value="#{vLoginController.user.userId}" />
<h:outputLabel for="inpassword" value="Password:" />
<p:password id="inpassword" size="20" value="#{vLoginController.user.password}" />
<f:facet name="footer">
<p:commandButton value="Login" process="#form" action="#{vLoginController.validateLogin}" update="logindialog"/>
<p:commandButton value="Sign up" action="#{vLoginController.showSignup}" update="logindialog, signupdialog"/>
</f:facet>
</h:panelGrid>
</p:dialog>
<p:dialog id="signupdialog" header="Sign up / Login" visible="#{vLoginController.signupDialog}"
draggable="false" resizable="false" modal="true">
<p:outputLabel>Test</p:outputLabel>
</p:dialog>
</h:form>
</ui:define>
Here is the supporting Bean
#Named
#SessionScoped
public class VLoginController extends BaseController implements Serializable {
private VUser user;
public VLoginController() {
}
public void placeOrderHomePage() {
loginDialog = true;
signupDialog = false;
}
public String validateLogin() {
// Validate the screen fields
FacesMessage msg = new FacesMessage();
msg.setSeverity(FacesMessage.SEVERITY_ERROR);
FacesContext context = FacesContext.getCurrentInstance();
if (user.getUserId() == null || user.getPassword() == null) {
msg.setSummary("Enter User ID and Password");
context.addMessage("screenvalidation", msg);
return null;
}
}
}
public class VUser implements Serializable {
public VUser() {
}
private int userSeq;
private String userId;
private String userType;
private String password;
private String salt;
private int active;
}
The userID and password in the user object are always null. Have gone through various forums content and tried like adding outputpanel around them etc., but none works. Have kept the code very similar to what the primefaces showcase says, still doesn't work.
Any solution please.. Please note that there is no problem in showing or hiding the dialog boxes, those logic works perfect. I just need to get the values entered by the user in the dialog fields to the bean..

Related

Strange bevavior of f:setPropertyActionListener inside ui:repeat and accordion

In a jsf/primefaces(version 6.2) project I have this peace of code to display a list of records in an accordion.
All the records are displayed correctly.
Inside a ui:repeat I have a p:commandButton to be able to save some text fragments (fragmt) using f:setPropertyActionListener.
I'm also implementing a second f:setPropertyActionListener to get an object (sRes). This one is working fine.
But the currentFrag variable get always populated with the text framgments from the last accordion.
<h:form id="accord" >
<p:accordionPanel value="#{myBean.lucSearchResults}" var="sRes" multiple="true">
<p:tab title="#{sRes.score}">
<ui:repeat value="#{sRes.frags}" var="fragmt">
<h:panelGrid columns="2" cellpadding="10">
<h:panelGrid columns="1" cellpadding="10">
<h:outputText value="#{fragmt}" escape="false"/>
<hr/>
</h:panelGrid>
<h:panelGrid columns="1" cellpadding="10">
<p:commandButton action="#{myBean.saveFrag}" value="Save" >
<f:setPropertyActionListener value="#{sRes}" target="#{myBean.currentSearchResult}" />
<f:setPropertyActionListener value="#{fragmt}" target="#{myBean.currentFrag}" />
</p:commandButton>
</h:panelGrid>
</h:panelGrid>
</ui:repeat>
</p:tab>
</p:accordionPanel>
</h:form>
I have a long experience with JSF and Java. I have no explanation for this strange behavior.
Any help or pointer on this issue is much appreciated.
I can reproduce this using Primefaces 7.0, Mojarra 2.3.3, JVM 1.8.0_152-b16, Apache Tomcat 9.0.21, Openwebbeans 2.0.7 using this example:
<h:form id="frm">
<p:accordionPanel id="accordion" value="#{myBean.cats}" var="cat"
multiple="true">
<p:tab id="tab" title="#{cat.name}">
<ui:repeat var="kid" value="#{cat.kitten}">
<h:panelGroup id="group">
<p:commandButton id="cmdSubmit" action="#{myBean.doSomething()}"
value="submit #{cat.name} - #{kid.name} " process="#form"
update=":frm:output">
<f:setPropertyActionListener value="#{cat}"
target="#{myBean.cat}" />
<f:setPropertyActionListener value="#{kid}"
target="#{myBean.kid}" />
</p:commandButton>
</h:panelGroup>
</ui:repeat>
</p:tab>
</p:accordionPanel>
<h:outputText id="output"
value="#{myBean.cat.name} - #{myBean.kid.name}" />
</h:form>
This is my bean:
package my.package;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
#Named
#ViewScoped
public class MyBean implements Serializable {
private static final long serialVersionUID = 43L;
private List<Cat> cats;
private Cat cat;
private Cat kid;
#PostConstruct
public void init() {
cats = new ArrayList<>();
for (int i = 0; i < 10; i++) {
final Cat cat = new Cat();
cats.add(cat);
cat.setName(String.valueOf(i));
cat.setKitten(new ArrayList<>());
for (int j = 0; j < 5; j++) {
final Cat kid = new Cat();
kid.setName(i + "." + j);
cat.getKitten().add(kid);
}
}
}
public void doSomething() {
System.err.println(cat.getName() + " / " + kid.getName());
}
// getters & setters ...
public static class Cat {
private String name;
private List<Cat> kitten;
// getters & setters ...
}
}
When hitting e.g. the command button reading "5 - 5.4" the output is "5 - 9.4":
When replacing p:accordion/p:tab with ui:repeat, this example works as expected. This suggests it has something todo with primefaces dynamic tabs and might be worth a bug report.
When replacing process="#form" with process="#this" or process="group" it also works as expected and outputs the correct label of the button pressed.
An even better work around for this is to use the p:repeat component implemented to solve known incompatibilities between tabView/accordion/dataTable and different ui:repeat implementations.

Control doesn't go into Primefaces LazyDataModel load method

I was able to see data in the datatable before adding the lazy attribute. After I added the lazy attribute, the datatable is empty, because my debug points were never reached which are inside the load method of LazyDataModel. In other words load method is not called, I see the control until this.searchResults in my search()
I just get my results from web services (which work just fine) I have looked at most of the links here and here. I made sure the lazy attribute and setRowCount are set. May be someone can help me out to figure out the problem. I am using PrimeFaces 6.0, CDI, JSF 2.2, Deltaspike 1.7.2
Here is my JSF
// other input form fields
<p:panel style="border-style : none;" styleClass="panelClass">
<h:panelGrid columns="2">
<!-- <h:commandButton action="#{search.search}" value="Search" styleClass="button_small_white" /> -->
<p:commandButton action="#{search.search}" ajax="true" update=":mainform:searchResultTable" value="Search" styleClass="button_small_white" />
<h:commandButton action="#{search.clear}" value="Clear" styleClass="button_small_white" />
</h:panelGrid>
</p:panel>
<br /><p:dataTable value="#{search.searchResults}" var="rec"
rowKey="rec.numTxt"
paginator="true" rows="10"
paginatorTemplate=" Display {RowsPerPageDropdown} Records {FirstPageLink}
{PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} "
rowsPerPageTemplate="10,25,50,100"
paginatorPosition="top"
rendered="#{not empty search.searchResults}"
id="searchResultTable"
widgetVar="searchTable"
lazy="true"
summary="RE Search Results are shown below">
<p:ajax event="page" listener="#{search.search}" update=":mainform:searchResultTable" />
<p:column headerText="">
<p:selectBooleanCheckbox value="#{rec.select}" />
</p:column>
...
</p:dataTable>
Controller
#Named("search")
#Stateful
#GroupedConversationScoped
#ConversationGroup(SearchGrp.class)
public class ReSearchController extends BaseWebServicesSearchController<ReSearchSummary>
implements ReGrp, ReSearchControllerLocal {
#Inject
private GroupedConversation conversation;
#Inject
private WindowContext windowContext;
private LazyDataModel<ReSearchSummary> searchResults;
...
#PostConstruct
#Override
public void init() {
// code for initializing my web services
search();
}
#Override
public String search(){
this.searchResults = new LazyDataModel<ReSearchSummary>() {
private static final long serialVersionUID = 4168363870903585956L;
#Override
public List<ReSearchSummary> load(int first, int pageSize, String sortField, SortOrder sortOrder,
Map<String, Object> filters) {
List<ReSearchSummary> resultsList = null;
resultsList = search(first, pageSize);
// rowCount
setRowCount(getResultCount());
// I do not need sorting oor filters os did not use them
return resultsList;
}
};
searchResults.setRowCount(getResultCount());
return "/cr-re-search.xhtml?faces-redirect=true";
}
#Override
public ArrayList<ReSearchSummary> search(int first, int pageSize){
// this is my webservice call, this works fine if I call it indepedently
// criteria gets the form inputs
return doSearch(criteria.getForm(), pageSize, first);
}
...
}
Update: Converted h:commandButton to p:commandButton for the search button
<p:commandButton action="#{search.search}" ajax="true" update=":mainform:searchResultTable" value="Search" styleClass="button_small_white" />
And added p:ajax inside p:dataTable
<p:ajax event="page" listener="#{search.search}" update=":mainform:searchResultTable" />

p:datatable: How to edit data in a p:dialog?

Context
I have a datatable with a button that opens a dialog when clicked. That dialog shows additional data (xml content) in a p:inputTextarea
Question
Now I would like to make this p:inputTextarea editable and have the changes reflected in the object of the datatable. I wanted to add a commandbutton in the dialog to save the changes. How do I get a reference to the selected object ?
Xhtml
<h:form id="alltxform">
<p:dataTable id="tablealltx" var="transaction" value="#{transactionListModel.txList}">
<p:column>
<p:commandButton update=":alltxform:xmlDetail" oncomplete="PF('dialog').show()">
<f:setPropertyActionListener value="#{transaction}"
target="#{transactionListModel.selectedTx}" />
</p:commandButton>
</p:column>
</p:dataTable>
<p:dialog header="Detail" widgetVar="dialog">
<p:outputPanel id="xmlDetail">
<p:inputTextarea readonly="false" id="xmlviewer"
value="#{transactionListModel.selectedTx.xml}" />
</p:outputPanel>
</p:dialog>
</h:form>
Model
package model;
#Named
#SessionScoped
public class TransactionListModel implements Serializable {
private static final long serialVersionUID = 1L;
private List<TransactionVO> txList;
private TransactionVO selectedTx;
public TransactionVO getSelectedTx() {
return selectedTx;
}
public void setSelectedTx(TransactionVO selectedTx) {
this.selectedTx = selectedTx;
}
#PostConstruct
public void init() {
txList = new ArrayList<TransactionVO>();
}
public List<TransactionVO> getTxList() {
return txList;
}
public void clearList(){
txList = new ArrayList<TransactionVO>();
}
}
Button
I want to add this button to the dialog.
<p:commandButton value="OK" onclick="PF('dialog').hide();" actionListener=""/>
I read about cellEdit events, but that's not really what I need. I need a reference to my transaction object inside the dialog in order to save the changes.
Do you mean the dialog will look like -
<p:dialog header="Detail" widgetVar="dialog">
<p:outputPanel id="xmlDetail">
<p:inputTextarea readonly="false" id="xmlviewer"
value="#{transactionListModel.selectedTx.xml}" />
<p:commandButton value="OK" onclick="PF('dialog').hide();" actionListener=""/>
</p:outputPanel>
</p:dialog>
And the action will refresh the model, before refreshing the table?
And you want to access TransactionListModel.selectedTx?
Well if its in the model and accessible from the controller then just -
actionListener="#{yourController.yourAction(transactionListModel.selectedTx)}"
And Update the underlying datastructure in the yourAction method, before updating :tablealltx:tablealltx

Primefaces datatable row selection does not work in viewscope

In my application I am using ViewScoped Bean and it does not show selected row when a row is selected in primefaces datatable. But if I changed the Bean to a SessionScoped Bean then it shows the selected row perfectly.
my code is like below.
<h:form id="form">
<p:growl id="msgs" showDetail="true" />
<p:dataTable var="pMData" rowIndexVar="rowIndex" value="# {managedBean.dataModel}" selectionMode="single" paginator="true" rows="100"
widgetVar="pMTable" emptyMessage="No Records Found." filteredValue="#{managedBean.filteredRecords}" selection="#{managedBean.selectedRecord}" rowKey="#{pMData.cellid}">
<p:ajax event="rowSelect" listener="#{managedBean.onRowSelect}"
update=":form:display :form:msgs" oncomplete="moreviewDialog.show()" />
<p:ajax event="rowUnselect" listener="#{managedBean.onRowUnselect}" update=":form:msgs"/>
<p:column headerText="Cell Name" filterBy="#{pMData.cellid}" filterStyle="display:none" >
<h:outputText value="#{pMData.modifiedCellID}" />
</p:column>
</p:dataTable>
<p:dialog header="History Data" widgetVar="moreviewDialog" resizable="false" id="moreviewDlg"
showEffect="fade" hideEffect="explode" modal="true">
<h:panelGrid id="display" columns="2" cellpadding="4" style="margin:0 auto;">
<p:lineChart id="category" value="# {managedBean.createCategoryModel(managedBean.selectedRecord.cellid)}" legendPosition="e"
title="NodeB Throughput(kbit/s)" minY="0" maxY="5000" style="height:300px;margin-top:20px"/>
</h:panelGrid>
</p:dialog>
</h:form>
and my managedBean CDI is like this.
#Named(value = "managedBean")
#ViewScoped
public class ManagedBean implements Serializable {
public void setSelectedRecord(PMData selectedRecord1){
this.selectedRecord=selectedRecord1;
}
public PMData getSelectedRecord(){
return selectedRecord;
}
public void onRowSelect(SelectEvent event) {
FacesMessage msg = new FacesMessage("NodeB Selected", String.valueOf(((PMData) event.getObject()).getCellid()));
FacesContext.getCurrentInstance().addMessage(null, msg);
}
public void onRowUnselect(UnselectEvent event) {
FacesMessage msg = new FacesMessage("Row Unselected",((PMData) event.getObject()).getCellid());
FacesContext.getCurrentInstance().addMessage(null, msg);
}
public PMDataModel getDataModel() {
return dataModel;
}
public CartesianChartModel createCategoryModel(String key) { .....}
public List<PMData> getFilteredRecords() {
return filteredRecords;
}
public void setFilteredRecords(List<PMData> filteredRecords) {
// System.out.println("came ");
this.filteredRecords = filteredRecords;
}
}
and PMData and PMDataModel classes are working normally. Can someone help me to select the row while still using viewscoped bean.
I think I found the answer. the error is with the dialogbox. I put dynamic=true in dialogbox. Now working perfectly.

PrimeFaces commandButton is not working

I know this is a very common issue which happens for a variety of reasons, but although I have searched about it a lot, I didn't manage to find a solution for my case.
My primefaces commandButton is inside an h:form and is declared as follows:
<p:commandButton action="#{userGroupBean.createOrUpdateItemAction}"
value="#{userGroupBean.actionCreateOrUpdateLabel}"
icon="iconDisk"
update="#form"
oncomplete="window.scrollTo(0,0);" />
My UserGroupBean is ViewScoped.
This button when clicked is supposed to create a userGroup and show a "Successful creation" message. Instead of doing this it just shows "Please wait" loader for a second and then does nothing. There are no errors in the log and through remote debugging I confirmed that it doesn't enter the action method.
The weird thing is that when I run the same code in a local Tomcat installation it runs successfully. Also, on the remote server this application is deployed, this used to work just fine. All happened suddenly, and I have a lot of commandButtons like this one, across my application which still work great. Something seems to go wrong just with this particular page .
I use PrimeFaces 3.1 version, I dont know what other information is usefull to provide.
Any help/ideas is/are appreciated.
EDIT
This is userGroup.xhtml (the page whose buttons do not work) code:
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:comps="http://java.sun.com/jsf/composite/components"
template="/WEB-INF/templates/userGroup/edit.xhtml">
<f:metadata>
<f:event type="preRenderView" listener="#{userGroupBean.initUserGroupUsersList}" />
</f:metadata>
<ui:define name="title">
User Group
</ui:define>
<ui:define name="centerUnit">
<h:form>
<h:panelGrid columns="3" styleClass="ui-messages-info ui-corner-all" rendered="#{not empty flash.messages_info}">
<span class="ui-message-info-icon"></span>
#{flash.messages_info}
</h:panelGrid>
<p:messages showDetail="true" globalOnly="true" />
<p:panel header="Settings">
<h:panelGrid columns="3" cellpadding="5">
<h:outputLabel for="title" value="User Group Title:" />
<p:inputText id="title" value="#{userGroupBean.userGroup.title}" />
<p:message for="title" />
</h:panelGrid>
</p:panel>
<p:panel header="Members">
<p:pickList value="#{userGroupBean.usersGroupUsersList}" var="user"
iconOnly="true"
converter="userConverter"
itemLabel="#{user.username}" itemValue="#{user}">
<f:facet name="sourceCaption">Available</f:facet>
<f:facet name="targetCaption">Participating</f:facet>
<p:column style="width:25%">
<p:graphicImage value="#{facesContext.externalContext.request.contextPath}/../file?thumbnail=&downloadPath=#{user.contactDetails.picture.downloadPath}" width="40" height="40" />
</p:column>
<p:column style="width:25%">
<h:outputText value="#{user.username}" />
</p:column>
<p:column style="width: 50%">
<h:outputText value="#{user.contactDetails.lastName} #{user.contactDetails.firstName}"/>
</p:column>
</p:pickList>
</p:panel>
<p:commandButton
action="#{userGroupBean.createOrUpdateItemAction}"
value="#{userGroupBean.actionCreateOrUpdateLabel}"
icon="iconDisk"
update="#form"
oncomplete="window.scrollTo(0,0);" />
<p:separator />
<p:outputPanel style="text-align:right" layout="block" rendered="#{!userGroupBean.userGroup.isNew() and userGroupBean.hasUserModifyUserGroupAuthority()}">
<h:panelGroup>
<p:commandButton value="Delete" title="Do you want to delete this user group?"
action="#{userGroupBean.deleteItemAction}"
update="#form"
icon="iconDelete" />
<p:commandButton value="Leave user group" title="I want to leave this user group"
action="#{userGroupBean.userInSessionLeavesUserGroupAction}"
update="#form"
icon="iconUserGo"/>
</h:panelGroup>
</p:outputPanel>
</h:form>
</ui:define>
The UserGroupBean.java:
#Controller("userGroupBean")
#Scope(value = "view")
public class UserGroupBean extends GenericBean<UserGroup> {
private static final long serialVersionUID = 1L;
final Log logger = LogFactory.getLog(getClass());
#Autowired
private SessionServiceImpl sessionService;
#Autowired
protected UserGroupService userGroupService;
#Autowired
protected UserService userService;
#Override
public String getPageCreateOrUpdate() { return "userGroup.xhtml"; }
#Override
public String getPageList() { return "../../my/userGroups.xhtml"; }
/** Wrapper method which calls getItem() */
public UserGroup getUserGroup() { return getItem(); }
/** Wrapper method which calls setItem() */
public void setUserGroup(UserGroup UserGroup) { setItem(UserGroup); }
protected UserGroup findItemById(Integer userGroupId) {
return userGroupService.findUserGroupById(userGroupId);
}
#Override
protected void resolveCreateRequest(HttpServletRequest req) {
logger.debug("UserGroupBean::resolveCreateRequest()");
setItem( userGroupService.initializeUserGroup("") );
}
#Override
protected String createItem() {
try {
if(!isValidUsersSelection(new ArrayList<User>(usersGroupUsersList.getTarget())))
return null;
List<Integer> userIds = new ArrayList<Integer>();
for(User user: usersGroupUsersList.getTarget())
userIds.add(user.getId());
userGroupService.saveUserGroup(getUserGroup(), userIds);
helperFacesContext.addInfoMessageToFlash("User Group successfully created.");
return getPageCreateOrUpdate()+"?action=update&id="+getItem().getId()+"&faces-redirect=true";
}
catch (Exception e) {
JsfUtils.error("There was an error", e.getMessage());
return null;
}
}
.....
}
And finally the UservConverter.java
#FacesConverter(value = "userConverter")
public class UserConverter extends GenericConverter {
final Log logger = LogFactory.getLog(getClass());
private UserDAO getUserDAO(FacesContext facesContext) {
// #Autowired gives null
return (UserDAO) FacesContextUtils.getWebApplicationContext(facesContext).getBean("userDAO");
}
/**
* converts the String representation of the key back to the Object
*/
#Override
public Object getAsObject(FacesContext context, UIComponent component,
String value) throws ConverterException {
logger.info("UserConverter::getAsObject("+value+")");
Integer userId = Integer.valueOf(value);
try {
return getUserDAO(context).findById(userId);
} catch(Exception e) {
throw new ConverterException(handleException(context,e.getMessage()));
}
}
NEW CLUE: When I restart the server and only after that, when I access this page and manage to create a user group before userGroup.xhtml is fully loaded, the user group is created just fine. If I restart the server and wait till the page is loaded and then create a user group again nothing happens. This problem will drive me crazy at the end.