Input value doesn't clear after validation failure - validation

I've searched a lot and haven't found a solution.
I'm using JSF 2.1 and RichFaces 4.2.3 and want to validate the login data of the user
I have two input fields.
One Username and one Password, both with #NotEmpty
login.xhtml
<html
xmlns="http://www.w3.org/1999/xhtml"
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:rich="http://richfaces.org/rich"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:mt="http://java.sun.com/jsf/composite/components">
<h:body>
<ui:composition template="/protected/user/login-template.xhtml">
<ui:define name="panel-navigation">
<ui:include src="/protected/user/login-left-menu.xhtml" />
</ui:define>
<ui:define name="contentbody">
<h:form>
<div id="content">
<div class="subcolumns">
<div class="c65l">
<div class="subcl">
<p class="sum-error-message" />
<fieldset>
<h3>
<h:outputText value="#{styleguideMessages.login}" />
</h3>
<p>
<h:outputText value="#{messages.login_text}" />
</p>
<div class="subcolumns">
<mt:inputText
id="loginName"
value="#{authenticationPM.loginName}"
label="#{messages.general_label_loginname}"
required="true" />
<div class="c33r validation"></div>
</div>
<div class="subcolumns">
<mt:inputText
id="password"
value="#{authenticationPM.password}"
label="#{styleguideMessages.db_password}"
required="true"
secret="true" />
<div class="c33r validation"></div>
</div>
<div class="subcolumns">
<h:commandLink
id="loginButton"
action="#{authenticationPM.doLogin}"
value="#{styleguideMessages.login}"
title="#{styleguideMessages.login}"
styleClass="button last" />
</div>
</fieldset>
</div>
</div>
</div>
</div>
<mt:commandButton
id="login"
action="#{authenticationPM.doLogin}"
value="hidden"
style="visibility:hidden" />
</h:form>
<script
src="#{facesContext.externalContext.requestContextPath}/js/lib/loginEnter.js"
type="text/javascript"
charset="utf-8"></script>
</ui:define>
</ui:composition>
AuthentificationPM.java
import *;
#Named
#SessionScoped
public class AuthenticationPM extends AbstractPM implements Serializable {
/**
* The user name from the login.
*/
private String userName;
/**
* password.
*/
private String password;
/**
* Returns the login name.
*
* #return String
*/
#NotNull
#Pattern(regexp = "^[^\"/\\[\\]:;|=,+?*<>]*$", message = "{user.loginname.pattern}")
public String getLoginName() {
return userName;
}
/**
* Returns the password.
*
* #return String
*/
#NotNull
public String getPassword() {
return password;
}
/**
* Sets the login name.
*
* #param loginName
* - the login name of the user
*/
public void setLoginName(String loginName) {
this.userName = loginName;
}
/**
* Sets the password.
*
* #param password
* - the password of the user
*/
public void setPassword(String password) {
this.password = password;
}
}
If one of those (say the password) is not filled, the validation fails and a message is shown (as it should).
Now I delete the username and type in a password.
The validation fails because the username is empty.
It cleans the password field and displays a message for the username.
And now the error happens: the former entered username reappeares!
How can I prevent this behaviour?
I know that after process validation, the update model values and invoke application are skipped and the render response is executed. As described here. The render response takes the values stored in the ui component (at apply requests) and uses them to rerender instead of deleting the invalid value.
I've tried this solution as well as this idea. Both ways don't find my component.
Any help or ideas are very appreciated.
Greetings,
Kevin

If you just erase the username from the inputfield, the value should be submitted as an empty string, which would be a legit replacement for the username and also matches the pattern defined.
I can only assume, that you have configured
<context-param>
<param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
<param-value>true</param-value>
</context-param>
in your web.xml. So, when you try to submitt an empty field, it is interpreted as null, which will not match your #NotNull Annotation on the username attribute. So, the setting of the value is canceled and it will maintain its prior state, cause it's SessionScoped - which is the username that has been entered once.
At least this is the only szenario a (String-)value is not updated when an empty string is submitted I can imagine.
Having this value set to true allows to reproduce the behavior you are describing.
You might ask, why this does not apply for your textbox where you are entering the password when erasing it? Since you are using secret="true" the text-box will not show any information about the string entered (i.e. the length), even if the backing bean attribute is not set to null (after removing the password) and still contains the wrong password.
But be aware that simply removing this attribute might screw functionality where other devs are relying on to get null instead of the empty string. So you should maybe consider to remove the #NotNull annotation and check for null manually.

Related

Render a component only when validation success

In JSF 2.X, can I render a component only when the validation success?
In my application I have many fields that must be filled. These data can be imported from a WebService through a search key.
When the user enter a valid search key the system searches the other fields and render them with the new values. But when the user enter a nonexistent key (or any other validation error) the server generates a validation error but still renders the fields, thus losing any data that there were filled.
What I need is that the user can perform the query and that if the query does not return results, this does not affect any data that he has already entered.
Below is a code example. Thus, if the user has filled in the fields inside updateThisOnSuccess and just after making an attempt to query without success, the value that is filled in is not lost.
<h:inputText value="#{controller.searchWebService}" >
<f:ajax execute="#this" render="updateThisOnSuccess messages" />
</h:inputText>
<h:panelGroup id="updateThisOnSuccess">
<h:inputText value="#{controller.field}" />
<!-- other fields -->
</h:panelGroup>
Submit the field values to run the search also does not seem an option as this will cause need to validate the fields inside updateThisOnSuccess.
Note: I saw the answer given by #BalusC to a similar question, but this is different from what I'm wondering why, in that case, foo-holder is always rendered and foo is conditioning. It's not my case, since this approach would make the controls do not appear when the validation fails.
Try this
<h:panelGroup id="updateThisOnSuccess">
<ui:fragment rendered="#{not facesContext.validationFailed}">
<h:inputText value="#{controller.field}" />
<!-- other fields -->
</ui:fragment>
</h:panelGroup>
Plaase try this. The requirements are that you must implement model validations with Bean Validation and the search field must implement JSF validation if required.
If you write "123456" then data is returned, else nothing is returned and a message is printed.
The backing bean:
#Named
#ViewScoped
public class yourBean implements Serializable{
private static final long serialVersionUID = 1L;
#Size(min=2)
private String field01;
private String searchWebService;
public void saveF(){
System.out.println("save");
}
public void searchWebServiceF(){
Boolean successWS = ("123456").equals(this.searchWebService);
if(successWS){
this.setField01("WS data");
}else{
FacesContext.getCurrentInstance().
addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "WS fails", ""));
}
}
public String getSearchWebService() {
return searchWebService;
}
public void setSearchWebService(String searchWebService) {
this.searchWebService = searchWebService;
}
public String getField01() {
return field01;
}
public void setField01(String field01) {
this.field01 = field01;
}
}
In your page:
<h:form id="form01">
<h:messages id="message"/>
<h:inputText id="wsid" value="#{pruebasBorradorBean.searchWebService}">
<f:validateLength maximum="6"/>
<f:ajax execute="#form" render="#form" listener="#{pruebasBorradorBean.searchWebServiceF()}" />
</h:inputText>
<h:panelGroup id="thedata">
<h:inputText value="#{pruebasBorradorBean.field01}">
<f:validateBean disabled="#{param['javax.faces.source']!='form01:save'}"/>
</h:inputText>
<!-- other fields -->
</h:panelGroup>
<h:commandButton id="save" value="submit">
<f:ajax render="thedata message" execute="#this thedata" listener="#{pruebasBorradorBean.saveF()}"/>
</h:commandButton>
</h:form>
You can change the components that will be processed in render phase changing the Collection at getRenderIds() of PartialViewContext. According to documentation this Collection is mutable.
FacesContext.getCurrentInstance().getPartialViewContext().getRenderIds().remove("formName:updateThisOnSuccess");
To test this solution, I used this controller:
#Named
#ViewScoped
public class Controller implements Serializable {
private static final long serialVersionUID = 1L;
private final static List<String> LIST_VALID_WEB_SERVICE_SEARCHS =
Arrays.asList(new String[] {"foo", "bar"});
private String webServiceParameter;
private Integer field01;
public void searchWebService() {
if (LIST_VALID_WEB_SERVICE_SEARCHS.contains(getWebServiceParameter())) {
setField01(123);
} else {
FacesContext facesContext = FacesContext.getCurrentInstance();
facesContext.getPartialViewContext().getRenderIds().remove("formFields");
FacesMessage facesMessage = new FacesMessage("Search not found in WebService.");
facesMessage.setSeverity(FacesMessage.SEVERITY_ERROR);
facesContext.addMessage("formName:searchWebService", facesMessage);
}
}
public void submit() {
System.out.println("submitted");
}
// Getters and Setters
}
And used this view:
<h:form id="formSearch">
<h:inputText id="webServiceParameter" value="#{controller.webServiceParameter}">
<f:ajax execute="#this" render="formFields messages" listener="#{controller.searchWebService}" />
</h:inputText><br />
</h:form>
<h:form id="formFields">
<h:inputText id="field01" value="#{controller.field01}" required="true">
<f:validateLongRange minimum="2" maximum="345" />
</h:inputText><br />
<!-- other fields -->
<h:commandButton value="submit" action="#{controller.submit}">
<f:ajax render="#form messages" execute="#form" />
</h:commandButton>
</h:form>
<h:messages id="messages" />
You can do something like that:
<f:ajax execute="#this" render="#{controller.success} message"/>
where success is a String attribute that will be empty if the WS fails and will be "updateThisOnSuccess" if not .
Or you could get rid of the JSF validation mechanism for informing the user the WS has failed. Think of it, it is not really a validation of the Model. You could draw an icon beside the WS Id field in red color or something similar using a boolean flag attribute in the backing bean.

ajax listener inside conditionally rendered element not working [duplicate]

This question already has an answer here:
h:commandButton is not working once I wrap it in a <h:panelGroup rendered>
(1 answer)
Closed 6 years ago.
Here is a test case of my problem:
TestBean:
#ManagedBean
#ViewScoped
public class TestBean implements Serializable {
private static final long serialVersionUID = -2329929006490721388L;
private List<TestObject> testObjects;
private int selectedId;
public TestBean(){
List<TestObject> to = new ArrayList<TestObject>();
for(int i=0; i<10; i++){
TestObject o = new TestObject(i, "object-"+i);
to.add(o);
}
this.setTestObjects(to);
}
public void testAjaxListener(int id){
System.out.println("testAjaxListener("+id+")");
this.setSelectedId(id);
}
//+getters/setters
}
TestObject
public class TestObject {
private int id;
private String name;
public TestObject(int id, String name){
this.setId(id);
this.setName(name);
}
//+getters/setters
}
Test.xhtml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head></h:head>
<h:body>
<h:form id="testForm">
<h:panelGroup rendered="#{param['view'] eq 'test'}">
<h2>DataTable</h2>
<h:dataTable var="o" value="#{testBean.testObjects}">
<h:column>
<h:commandLink value="#{o.name}" actionListener="#{testBean.testAjaxListener(o.id)}">
<f:ajax
render=":testForm:outputTest"
/>
</h:commandLink>
</h:column>
</h:dataTable>
<h2>output</h2>
<h:outputText id="outputTest" value="#{testBean.selectedId}" />
</h:panelGroup>
</h:form>
</h:body>
</html>
The problem is, that actionListener won't firing (i'm checking that with System.out.print as you can see). It works fine when i remove conditional render from panelGroup, so i think that is the issue - but how can i fix it?
I have readed those topics:
h:commandLink / h:commandButton is not being invoked,
f:ajax inside conditionally rendered custom tag - backing bean method not invoked
and many more, but it didn't solve my problem :(
Please help
It's because the #{param['view'] eq 'test'} didn't evaluate true while JSF is busy processing the ajax submit. It will then also consult the rendered, disabled and readonly attributes once again as safeguard against hacked requests. JSF namely doesn't include the request parameters in the <form action> URL as generated by <h:form>. This matches point 5 of commandButton/commandLink/ajax action/listener method not invoked or input value not updated.
There are several ways to get around this.
Set it as a property of the view scoped bean via <f:viewParam>.
<f:metadata>
<f:viewParam name="view" value="#{testBean.view}" />
</f:metadata>
...
<h:panelGroup rendered="#{testBean.view eq 'test'}">
Manually retain the param via <f:param> (you need to put it in every submit action!):
<h:commandLink ...>
<f:param name="view" value="#{param.view}" />
...
</h:commandLink>
Replace <h:form> by OmniFaces <o:form> which is capable of telling JSF that it must submit the form to an URL including the request parameters:
<o:form includeRequestParams="true">
...
</o:form>
See also:
Retaining GET request query string parameters on JSF form submit

retaining values across screen sin JSF2.0

I am working on JSF2.0 project where I need to get value in backing bean from previous screen I have explained it below
my first screen
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
>
<h:body>
<h:form>
<h:outputText value="LocationID" />
<h:inputText value="#{getDetails.locationID}"/>
<h:commandButton value="Add OS" action="#{getDetails.addOSDetails}"/>
</h:form>
</h:body>
</html>
My backing bean when the commandButton is invoked
#ManagedBean(name="getDetails")
#RequestScoped
public class GetDetailsBean {
private String locationID;
public String getLocationID() {
return locationID;
}
public void setLocationID(String locationID) {
this.locationID = locationID;
}
public String addOSDetails(){
return "/app_pages/addOS";
}
}
My second screen which is addOS is
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
>
<h:body>
<h:form>
<h:outputText value="Enter Value" />
<h:inputText value="#{addOS.addValue}"/>
<h:commandButton value="Add OS" action="#{addOS.save}"/>
</h:form>
</h:body>
</html>
I want the LocationID entered in the first screen to be available in this backing bean
#ManagedBean(name="addOS")
#RequestScoped
public class AddOS {
private String addValue;
public String getAddValue() {
return addValue;
}
public void setAddValue(String addValue) {
this.addValue = addValue;
}
public String save(){
return "app_pages/success";
}
}
I donot want values to be set in session.Can be used.
Thoughts and help please
Thanks.
If you really intend to do a forward, as you do in your question, the submitted on the first page data is already there when the second page is rendered: remember, the forward is done within the same HTTP request. So, what you ultimately need is to keep the value for a subsequesnt POST request. You can do it, for example, by storing the information is a hidden field on the second page:
<h:inputHidden value="#{getDetails.locationID}" />
And that's basically it.
If you intend to do a redirect, thus by appending ?faces-redirect=true to a navigation case outcome, you need to store that information in EL flash to be able to retrieve it in the recepient page: there are two requests to be done. So, change your first bean's action method to the following:
public String action() {
...
FacesContext.getCurrentInstance().getExternalContext().getFlash().put("locationID", locationID);
return "result?faces-redirect=true";
}
This way on the recepient page it will be available in flash map, thus by
#{flash.locationID}
in EL scope and
(String)FacesContext.getCurrentInstance().getExternalContext()
.getFlash().get("locationID");
in Java code.

Having multiple validation functions in a class with multiple actions

I want to validate forms in Struts 2 using validate functions in the action class.
I found this example : http://www.javatpoint.com/struts-2-custom-validation-workflow-interceptor
However, I want to have multiple functions (actions) in the same class. And I want to have a validation function for each of these functions. How can we do this?
Edit:
The validate() function in the example gets invoked automatically since it is one of the Validateable interface functions. If I have validate functions with other names they won't be invoked
Create validateXxx methods where Xxx is the name of the related action method.
(Whether or not this is the best option depends on the particular validations you need.)
validations using XML validation file
The naming convention of the XML validation file should be ActionClass-Validation.xml. Here our Action Class name is "Login.java" and the XML validation file name is "Login-Validation.xml".
The Login-Validation.xml file contains the following code.
view source
print?
<validators>
<field name="userName">
<field-validator type="requiredstring">
<message>User Name is required.</message>
</field-validator>
</field>
<field name="password">
<field-validator type="requiredstring">
<message key="password.required" />
</field-validator>
</field>
</validators>
The field element contains the name of the form property that needs to be validated. The filed-validator element inside the field element contains the type of validation that needs to be performed.
Here you can either specify the error message directly using the message element or you can use the properties file to define all the error messages and use the key attribute to specify the error key.
Note the properties file should also have the same name as the Action class.
The Login Action class contains the following code.
view source
print?
public class Login extends ActionSupport {
private String userName;
private String password;
public Login() {
}
public String execute() {
return SUCCESS;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
The login.jsp page contains the following code.
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<%#taglib uri="/struts-tags" prefix="s" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Login Page</title>
<s:head />
</head>
<body>
<s:form action="LoginAction">
<s:textfield name="userName" label="User Name" />
<s:password name="password" label="Password" />
<s:submit value="Login" />
</s:form>
</body>
</html>

Primefaces: Editable object in accordionPanel with Dynamic = True

I am trying to achieve functionality where I am generating the tabs in according panel dynamically according to the list.
List is of say some object e.g Person
Now attribute corresponding to each person, I am showing in each tab in a form.
Values are loaded correctly but when I edit those value I am not getting updated values at the backing bean, I am getting only old values.
Can somebody please explain why ?
Here is the code.
Person Object
public class Person {
String name;
//getter setter
#Override
public String toString() {
return name;
}
}
Backing Bean
#ManagedBean(name = "editor")
public class EditorBean {
private List<Person> persons = new ArrayList<Person>();
#PostConstruct
void init() {
persons.add(new Person("dhruv"));
persons.add(new Person("tarun"));
}
public void testAction() {
System.out.println(persons);
}
// Getter Setter*****************//
public List<Person> getPersons() {
return persons;
}
public void setPersons(List<Person> persons) {
this.persons = persons;
}
}
XHTML Code:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<h1>Hello World PrimeFaces</h1>
<h:form>
<p:accordionPanel value="#{editor.persons}" var="person" dynamic="true">
<p:tab title="#{person}">
<p:inputText value="#{person.name}"></p:inputText>
</p:tab>
</p:accordionPanel>
<p:commandButton action="#{editor.testAction()}" value="testAction"></p:commandButton>
</h:form>
</h:body>
</html>
When I run the same with with dynamic="false". This works fine. But in my real scenario I have lots of data which I cannot afford to paint in one go thats why I want to use dynamic = true.
Can somebody explain how to achieve this if not by dynamic = true ??
The reason you're having stale values in your accordion is that dynamic accordions default to cache="true". This attribute causes the accordion to not reload new/updated values. To cause an ajax refresh on tab open, set cache="false" on your accordion

Resources