JSF 2 ProcessValidationPhase Fails Due to Uninitialized Managed Bean Property - spring

I am looking for best-practice guidance on how to implement the following. I am using JSF2, Spring 3, PrimeFaces 3.3, MyBatis.
REQUIREMENT:
I have a data entry screen with input fields linked to VO object which is a property on the managed bean. The user can either create a new record, or search for existing records to edit.
When the edit an existing record option is selected, a dialog box appears where the user is able to search and retrieve a list of potential records to select from.
They are only able to select one record to edit at a time. Once they have made their selection, the dialog box closes, and the VO object is populated with the selected data ready for the user to edit.
PROBLEM:
When the search form is submitted to retrieve a list of potential records for editing, the VO object has not yet been initialised and causes the ProcessValidationPhase to fail the process with a "Target Unreachable".
What is the best way to implement this scenario? Should the VO object be initialised with blank values in the managed bean? Or should there be an initialise method on the VO object that is called during the initialisation of the managed bean?
DataEntry.XHTML
The main data entry fields:
<p:panelGrid id="dataEntry">
<p:row>
<p:column style="width:200px;">
<h:outputLabel value="Field 1:"/></p:column>
<p:column>
<p:inputText value="#{managedBean.dataEntryVo.field1}"
style="width:50px;"
disabled="true"/>
</p:column>
</p:row>
<p:row>
<p:column>
<h:outputLabel value="Field 2:"/>
</p:column>
<p:column>
<p:inputText value="#{managedBean.dataEntryVo.field2}"
style="width:50px;"
disabled="true"/>
</p:column>
</p:row>
</p:panelGrid>
The command button on the dialog box used to retrieve a list of possible records for selection to edit:
<p:commandButton id="retrieveDataCb"
value="Retrieve"
actionListener="#{managedBean.retrieveDataEntryList}"
update=":dataEntryForm:retrievedList">
</p:commandButton>
Many thanks

Initialising the search criterion to a dummy object will definitely work. Not very neat but it works. On the other hand, you could try using a data container component like a <p:dataGrid/> or <p:dataTable/>. There is a var attribute that will let you get away with null references like the case that you are trying to achieve. The var attribute compensates for empty datasets. That being said, you can now have a List<DataEntryVo> in your backing bean and then in your view:
<p:dataGrid id="dataEntry" value="#{managedBean.theVoList}" var="vo">
<p:panel>
<p:panelGrid>
<p:column style="width:200px;">
<h:outputLabel value="Field 1:"/>
</p:column>
<p:column>
<p:inputText value="#{vo.field1}" style="width:50px;" disabled"true"/>
</p:column>
<p:row>
<p:column>
<h:outputLabel value="Field 2:"/>
</p:column>
<p:column>
<p:inputText value="#{vo.field2}" style="width:50px;" disabled="true"/>
</p:column>
</p:row>
</p:panelGrid>
</p:panel>
</p:dataGrid>
Another alternative, you could avoid binding the input fields to an object in your managed bean altogether, instead binding the input fields to the managed bean directly as in <p:inputText binding="#{vo.field1Input}" style="width:50px;" disabled="true"/> and in your backing bean you will have UIcomponent field1Input = new HtmlInputText(); (or whatever the class is for primefaces and then call field1Input.getValue() or field1Input.setValue() according to your needs. It's also a good idea to make your bean a ViewScoped bean to avoid unnecessary trouble getting this solution to work.

Related

Primefaces p:overlayPanel is empty when update attribute is used in child tag

I want to show a list of key-value pairs in a datatable, where each pair is one row, inside an overlay panel. When a key-value pair is clicked, i want to update a <p:inputText>-Element, which is OUTSIDE the overlaypanel with the key-value of the selected row and simultaniously close the overlaypanel.
I just migrated from PF 4.0 to PF 6.1 and now im facing the issue, that whenever i use an update-attirbute inside the overlay panel, it appears to be empty and no content is shown.
here is an code example:
<p:inputText
id="inputPvId"
styleClass="form_input"
readonly="true"
value="#{bean.selectedValue.get(0)}" />
<p:commandButton
icon="ui-icon-link"
id="selectValue"
value="#{msg_properties.chooseValue}" />
<p:overlayPanel
for="selectValue"
id="overlayValueSelector"
widgetVar="overlayValueSelector
dynamic="true"
styleClass="form_input_widest">
<p:dataTable
var="car"
value="#{dtBasicView.cars}">
<p:column
headerText="Id">
<h:outputText
value="#{car.id}" />
</p:column>
<p:column
headerText="Year">
<h:outputText
value="#{car.year}" />
</p:column>
<p:ajax
event="rowSelect"
update=":form:inputPvId,:form:myTable"
onsuccess="PF('overlayPV').hide()" />
</p:dataTable>
Previously it worked that way. All I changed is the way the Widget gets called from "overlayPV".hide()" to "PF('overlayPV').hide()" as the official Migration Guide suggested. If out cancel out the update=":form:inputPvId,:form:myTable" line in the ajax call, the content is shown properly.
Am I doing somethign wrong? My research showed, that other people also had trouble with the overlaypanel and the ajax update. However, i found no suitable solution for my problem.
I tried using the "onRowClick"-Attribute of the datable along with the widgetHide call like this:
<p:dataTable
onRowClick="PF('overlayPV').hide()" />
and it worked fine, however i could not figure out how to update the <p:inputText>-Element with the choosen value. I had to refresh the page to show the new value. I would be happy if someone suggested a solution for this. Thanks in advance.
I finally resolved the issue.
My initial problem was, that whenever an element inside the <p:overlayPanel> included the "update" attribute, the overlayPanel did not render any content and appeared empty.
i solved my issue with the <p:remoteCommand>-Tag, which I placed OUTSIDE of the overlayPanel as my example Code below shows:
<p:inputText
id="inputPvId"
styleClass="form_input"
readonly="true"
value="#{bean.selectedValue.get(0)}" />
<p:commandButton
icon="ui-icon-link"
id="selectValue"
value="#{msg_properties.chooseValue}" />
<p:overlayPanel
for="selectValue"
id="overlayValueSelector"
widgetVar="overlayValueSelector
dynamic="true"
styleClass="form_input_widest">
<p:dataTable
var="myTable"
value="#{dtBasicView.cars}"
onRowClick="remoteCommand()">
<p:column
headerText="Id">
<h:outputText
value="#{car.id}" />
</p:column>
<p:column
headerText="Year">
<h:outputText
value="#{car.year}" />
</p:column>
</p:dataTable>
</p:overlayPanel>
<p:remoteCommand
name="remoteCommand"
update="inputPvId, myTable"
onsuccess="PF('overlayPV').hide()"/>
Note the onRowClick-Attribute of my dataTable which call the remoteCommand outside of te overlayPanel. The remoteCommand than updates all my Elements that need to be updated and also closes the overlayPanel.

Why are fields reset after ajax update with Primefaces

On a form I have some personal information (name, address etc.) and a changeListener which updates the salutation and letter salutation according to the gender and last name. If the underlying entity was already stored in the database it works fine. If I'm entering data for a new (not saved) entry the form gets reset after the listener has been called. All data entered is lost, only the salutation, lettersalutation which I modify in the listener and gender, name which I use and attached a ajax call on are kept.
This is a part of the form:
<h:form id="person">
<p:panel header="#{msg['prs']}">
<h:panelGrid columns="6" cellpadding="4">
<h:outputText value="#{msg['prs.salutation']}"/>
<p:inputText value="#{personBean.selectedPerson.salutation}"/>
<h:outputText value="#{msg['prs.lettersalutation']}"/>
<p:inputText value="#{personBean.selectedPerson.letterSalutation}"/>
<p:spacer/><p:spacer/>
<h:outputText value="#{msg['prs.name']}: "/>
<p:inputText value="#{personBean.selectedPerson.name}">
<p:ajax event="change" update="person"
listener="#{personBean.selectedPerson.updateSalutation}" />
</p:inputText>
<h:outputText value="#{msg['prs.surname']}: "/>
<p:inputText value="#{personBean.selectedPerson.surname}"/>
<h:outputText value="#{msg['prs.gender']}: "/>
<p:selectOneMenu value="#{personBean.selectedPerson.gender}">
<f:selectItems value="#{enumHelper.getEnum('Gender')}"/>
<p:ajax event="change" update="person"
listener="#{personBean.selectedPerson.updateSalutation}" />
</p:selectOneMenu>
</p:panel>
</h:form>
In the code I do then the updates.
public void updateSalutation() {
// simplified
letterSalutation = "...";
salutation = "...";
// outputs for debug
System.out.println(this.getName()); // --> not null
System.out.println(this.getSurname()); // --> null
}
Already here in this call surname, which is not attached to a ajax call is null even though data was entered there. The same is true for all the other fields. In my application I'm using Primefaces, JavaEE 1.6 with Wildfly.
What is the reason for that behavior? Is there anything I can change on my calls to prevent this?
Why are fields reset after ajax update with Primefaces
This problem has 2 possible causes depending on the concrete functional requirement:
It's because you didn't tell JSF to process the desired input values.
Or, it's because you told JSF to also update the non-desired input values.
The solution depends on the cause:
Add process="person" (or process="#form") to <p:ajax> to process the whole form.
Or, edit update="person" to specify only the components which really need to be updated.
Given your complaint in the end of the question, I believe you're looking for #1.
See also:
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes
My solution:
Include the content that I want to update in a
<p:panel id="toUpdate">
and make a
update="toUpdate"

How to pass a parameter in p:ajax when we used it with p:inputText?

I need to pass a parameter in my p:ajax method . there is a <p:inputText> and when I finish typing my input Box have to update my p:ajax method. But i am not able to send the parameter in my method.
My jsf page is :
<h:outputText value="#{msg['elicense.contractorFormRenewal.personal.registrationNo']}"/>
<p:inputText id="registrationNo" value="#{renewalContractorBean.registrationNo}" required="false" label="Registration No">
<p:ajaxlistener="#{renewalContractorBean.readLicenseDetailsById(renewalContractorBean.registrationNo)}/>
</p:inputText>
and my method in bean is
public void readLicenseDetailsById(String id) {
FirmOrCompany firmOrCompany = contractorRenewableService.readLicenseDetailsById(id);
this.setLicenseName(firmOrCompany.getLicensePersonName());
this.setClassofLicense(firmOrCompany.getLicenseAppliedFor());
}
There is no <p:ajaxListener>, i don't know if you missed your code or the question.
Considering you made a mistake in the question, your method should work fine, you just forgot to set the event=blur in <p:ajax>, so it get called once you leave the inputTextBox(means that the user already done typing)
<p:inputText id="registrationNo" value="#{renewalContractorBean.registrationNo}" required="false" label="Registration No">
<p:ajax event="blur" listener="#{renewalContractorBean.readLicenseDetailsById()}/>
</p:inputText>
Check that if you want to update another component, based on the changes you made in your bean, you must specify the id of that component in <p:ajax>, <p:ajax event="blur" update"IdOfTheComponent" ....>
Also, you don't have to pass properties which is already in your bean as a parameter, you can just get it in your bean.
Finally, in renewalContractorBean:
public void readLicenseDetailsById()
{
String id = this.registrationNo;
FirmOrCompany firmOrCompany= contractorRenewableService.readLicenseDetailsById(id);
this.setLicenseName(firmOrCompany.getLicensePersonName());
this.setClassofLicense(firmOrCompany.getLicenseAppliedFor());
}
Hi did you tryupdate="tableid" ? When I delete from a list which in p:dataTable, JSF can update this dataTable I hope this will be helpful.
Here is my code to update my p:datatable
<p:dataTable id="tbl" value="#{borrowerBean.borrowers}" var="bor">
<p:column>
<f:facet name="header">
<h:outputLabel>ID: </h:outputLabel>
</f:facet>
<h:outputLabel value="#{bor.id}"/>
</p:column>
.
.
.
<p:commandButton value="Delete" action="#{user.deleteBorrower(bor.id)}" update="tbl"/>
</p:column>
</p:dataTable>

Ajax validation, different Messages

Hi guys I have a real problem with my validation in JSF. I want to validate a Mail-Address if it's already used and the correct mail format. Here are the picture how it should look.
https://www.dropbox.com/s/bs9nshmuurauc2e/Unbenannt.JPG
I hope can understand the problem. I don't now how I can implement it.
Can I set different messages for different events?
I use primefaces 3.5 and jsf 2.1
<p:row>
<p:column style="width:400px">
<h:outputLabel for="email" styleClass="outputRight" value="#{msg['regi_mail']}" />
</p:column>
<p:column style="width:350px">
<p:inputText style="width:350px" requiredMessage="#{msg['regi_mail_valid']}" validatorMessage="#{msg['regi_mail_valid']}" id="email" value="#{regiBean.user.EMAIL}" required="true">
<f:validateRegex pattern="^[_A-Za-z0-9-\+]+(\.[_A-Za-z0-9-]+)*#[A-Za-z0-9-]+(\.[A-Za-z0-9]+)*(\.[A-Za-z]{2,})$" />
<f:ajax event="blur" render="format user" />
</p:inputText>
</p:column>
<p:column style="width:410px">
<h:panelGroup id="mail" class="fa fa-question-circle fa-2x" />
<p:overlayPanel for="mail" showEvent="mouseover" hideEvent="mouseout" hideEffect="fade">
<p:panel>
TEXTTEXTTEXT
</p:panel>
</p:overlayPanel>
<p:message id="format" for="email" />
</p:column>
</p:row>
<p:row>
<p:column style="width:400px">
<h:outputLabel styleClass="outputRight" value="Username" />
</p:column>
<p:column style="width:350px">
<h:outputLabel id="user" style="color: green;" value="#{regiBean.user.EMAIL}" />
</p:column>
<p:column>
<h:panelGroup id="us" class="fa fa-minus-square fa-2x" />
<h:panelGroup/>
</p:column>
</p:row>
I've done something like this but front end only different.
XHTML File
The Bean Code
I hope you will get some help from this.
This may be a little late, I see the question was asked in Feb already. However, seems this would be a case where you should rather supply a custom validator. Here is my suggestion:
Remove the validatorMessage attribute from you id="email" element. Also remove the f:validateRegex validator in that input element.
Create a custom validator. It should:
Have a #ManagedBean (or similar) annotation (so that the EL in your JSF page can reference it)
implement javax.faces.validator.Validator
override the validate() method. In it you do your validations, e.g. check your regexp as well as query the database for existing addresses via e.g. JPA (or an EJB business method). If validation fails, you throw a javax.faces.validator.ValidatorException, that is constructed with a javax.faces.application.FacesMessage instance containing the relevant error message (there are various constructors, find an applicable one).
If you do not want to code something in this validator, but "pass it in" from the JSF page, you could do that via attribute passing. Useful if you e.g. would want to pass in your (i18z'ed) error message, values of other fields on the form, etc. etc. The only things available inside the validate() method by default is the FacesContext, the UIComponent, and the value that is validated. (See example below.)
Modify your JSF similar to the example below.
Example - Validator class:
#ManagedBean public class MyEmailValidator implements Validator {
#EJB UserEJBLocal userEJB; // supposing you want to use a method in there to get list of e-mail addresses
private static final String REGEXP = "^[_A-Za-z0-9-\+]+(\.[_A-Za-z0-9-]+)*#[A-Za-z0-9-]+(\.[A-Za-z0-9]+)*(\.[A-Za-z]{2,})$";
#Override public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
if (! Pattern.matches(REGEXP, value.toString())) {
throw new ValidatorException(new FacesMessage(component.getAttributes().get("formatMsg")));
}
List existingAddresses = userEJB.getAllAddresses(); // or whatever method your are using to obtain current addresses, e.g. JPA.
if (existingAddresses.contains(value.toString()) {
throw new ValidatorException(new FacesMessage(
FacesMessage.SEVERITY_ERROR,
"The address already exists." // could also be passed in as attribute, etc.
));
}
}
}
Example - JSF snippet:
<p:inputText id="email" value="#{regiBean.user.EMAIL}"
requiredMessage="#{msg['regi_mail_valid']}" required="true"
>
<f:validator binding="${myEmailValidator}" />
<f:attribute name="formatMsg" value="#{msg['regi_mail_valid']}" />
: <!-- other attributes, if needed -->
<f:ajax event="blur" render="email-msg user" />
</p:inputText>
:
<p:message id="email-msg" for="email" />
Well, the above example may not be complete, but might point you in the right direction.
OK, so maybe you want to check the current row's e-mail against the e-mails in the other rows? You are a bit out of luck... The only way I can think of is to somehow gather them all into a list, which you can pass via another attribute to the validator. Not very easy with a dynamic table... You might want to rethink your process.

p:inputText in p:dataTable not setting the value in the bean

I'm trying to implement a dataTable which contains (among other things) a column with a textInput so I can modify a string value in the bean. My problem is that the bean does not update correctly, so this is part of my code:
<p:scrollPanel style="height:625px" mode="native">
<p:dataTable value="#{oaBean.documentos}" var="documento"
rowIndexVar="rowIndexVar" rowKeyVar="documentoKey" id="documentoList"
widgetVar="myTableWidget" paginator="true" rows="50"
emptyMessage="#{messages['norecords']}">
<f:facet name="header">
<h:outputText value="#{messages['documents']}" />
</f:facet>
<p:column style="width:1px;margin:0;padding:0;" headerText="#">
<h:outputText value="#{rowIndexVar+1}"
style="font-size:0.75em;margin:0;padding:0;" />
</p:column>
//lots of another columns
<p:column headerText="#{messages['documento.orden']}"
style="width:25px; text-align: center" id="columnOrden" widgetVar="columnOrden">
<p:inputText id="ordenDocumento" value="#{documento.orden}"
disabled="#{documento.eliminado}" style="font-size:0.9em" size="2"
validator="floatValidator">
</p:inputText>
</p:column>
</p:dataTable>
</p:scrollPanel>
The thing is that when the control returns to the bean the value of orden is not updated, I always have the old value. I've also tried adding an ajax listener for the change event and it seems to work fine, but if I change for example, 5 rows, at least one of them maintains the old value, so my question is: is there any known problem with dataTables and textInputs? Is something wrong with my code?
Any help will be really appreciated, thanks in advance guys.
UPDATE
Sorry, I've forgot to include some information. First of all, I'm working with Mojarra 2.1.5, PrimeFaces 3.4.2 and Facelets and running in Tomcat 7. Second, and probably the most important, the code presented above is included through a tab into a larger xhtml:
<ui:define name="body">
<rich:panel styleClass="createFormPanel">
<h:panelGroup layout="block" style="margin:0 auto;width:100%;" id="principalPanel">
<div style="height: 665px"><p:tabView id="tabs" widgetVar="tabsView" activeIndex="#{oaBean.activeTab}">
<p:tab id="tab5" title="#{messages['oa.tab.contenido']}">
<h:form id="formTab2">
<ui:include src="/pages/oa/tabContenido.xhtml" />
</h:form>
</p:tab>
</p:tabView></div>
</h:panelGroup>
</rich:panel>
</ui:define>
In this case, tabContenido.xhtml is the page containing the data table definition. Didn't include the java code because is just a bean with getter and setter values. If you need more information just let me know.
Regards.
Try adding an ajax event to the column and updating the hole table, something like this:
<p:column headerText="#{messages['documento.orden']}"
style="width:25px; text-align: center" id="columnOrden">
<p:inputText id="ordenDocumento" value="#{documento.orden}"
disabled="#{documento.eliminado}" style="font-size:0.9em" size="2"
validator="floatValidator">
<p:ajax event="change" update="documentoList" />
</p:inputText>
</p:column>

Resources