Reputation: 697
I have created a class to test a person object with. e.g.
public class PersonValidators implements Serializable {
private static final long serialVersionUID = 1L;
public PersonValidators(){
}
public void valIdNumber(FacesContext facesContext, UIComponent component, Object value) {
System.out.println(this.getClass().getSimpleName().toString() + " - valId(...), value=" + value.toString());
String msg = "Invalid id for person provided";
FacesContext.getCurrentInstance().addMessage(null, new javax.faces.application.FacesMessage(javax.faces.application.FacesMessage.SEVERITY_INFO, msg, ""));
}
}
And I have registered as a managed bean as followed:
<managed-bean>
<managed-bean-name>personValidators</managed-bean-name>
<managed-bean-class>com.mybank.mycard.test.PersonValidators</managed-bean-class>
<managed-bean-scope>view</managed-bean-scope>
</managed-bean>
For my control I have defined to use the method as Validator:
<xp:inputText id="idNumber"
value="#{personBean.person.idNumber}"
disabled="#{!personBean.person.editable}"
validator="#{personValidators.valIdNumber}" required="true">
<xp:this.validators>
<xp:validateRequired
message="Field PassNumber is empty">
</xp:validateRequired>
</xp:this.validators>
</xp:inputText>
On the xpage I have added a messages control:
<xp:panel
rendered="#{javascript:facesContext.getMessages().hasNext()}"
style="margin-top:15px;">
<div class="row">
<div class="col-md-12">
<xp:panel>
<xp:this.styleClass><![CDATA[#{javascript:return "alert alert-danger"}]]></xp:this.styleClass>
<xp:messages id="msgBox"></xp:messages>
</xp:panel>
</div>
</div>
</xp:panel>
In the xsp.properties I have set:
xsp.client.validation=false
The problem is that the message from my validator class NEVER appears in the messages control.
What do I have overlooked?
UPDATE:
I did not post the code that initializes the validation:
<xp:button value="Save" id="SaveButton"
styleClass="btn-primary" rendered="#{personBean.person.editable}">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action>
<xp:actionGroup>
<xp:confirm
message="Are you sure you want to submit this case?" />
<xp:executeScript>
<xp:this.script><![CDATA[#{javascript:personBean.save();
facesContext.getExternalContext().redirect("person.xsp?custId=" + personBean.getPerson().getCustomer().getCustId())}]]></xp:this.script>
</xp:executeScript>
</xp:actionGroup>
</xp:this.action>
</xp:eventHandler>
</xp:button>
When I remove the facesContext... the message is displayed. If I add it the xpages will be re-routed.
How can I prevent this?
I though the XPage would not be continue with the next phase when a message was added to the facescontext :-?
Upvotes: 2
Views: 130
Reputation: 244
I have reproduced your code snippets and the message from valIdNumber
is successfully displayed in messages control. The only difference that I've set the value of inputText
component to the viewScope
variable instead of managed bean field and removed the disabled
property, but that should not matter.
The method won't fire if inputText
has no value entered, in this case only validateRequired
's message will be displayed.
Do you always see the println
output in server console as the evidence that the method was at least fired?
Update:
This happens because in your case the InvokeApplication
phase, where your redirect (and save!) are done, is executed anyway, even if your validator fails. You should explicitly tell the engine that you don't want to proceed.
Add the following lines to your validation method before return:
UIInput myInput = (UIInput)component;
myInput.setValid(false);
These lines should execute in the same conditional block where FacesContext.addMessage
executes, i.e. when validation fails.
One more solution is to throw a ValidatorException
instead when your check fails, it will automatically set the component as invalid and will tell the lifecycle management process to jump to RenderResponse
phase, avoiding UpdateModel
and InvokeApplication
phases. You can also provide your custom message in ValidatorException
constructor and it will be automatically added to FacesContext
:
throw new javax.faces.validator.ValidatorException(
new FacesMessage("Invalid id for person provided")
);
Upvotes: 2