2 Replies Latest reply on Aug 20, 2012 5:34 PM by snandula

    Graph Validator

    snandula

      I am using rich graph validator hoping to validate an object. The graph validator is an interface with one method called validateGraph which takes in an object and validates it.

      The default implementation for this interface is org.richfaces.validator.FacesBeanValidator.

       

      This class implements both the Validator interface and the GraphValidator interrface and the corresponding methods implemented.

       

      when my application is invoked, i observed that the validate method is being invoked rather than the validateGraph method. Why is this the case? when i used rich:graphValidator in my JSF Application, i would logically assume that the method validateGraph should be invoked correct?

       

      Can someone help me understand how i can get the validateGraph method invoked?

       

      Many thanks for this help.

        • 1. Re: Graph Validator
          healeyb

          Why are you using rich:graphValidator to validate a single object? surely the idea is to use it to this to perform

          bean validation in the process validations phase when all components (that are children of the graphValidator tag)

          have passed validation.

           

          For a single object is it not more straightforward to just use a custom validator? It would be easier if you'd post

          some code up really.

           

          Regards,

          Brendan.

          • 2. Re: Graph Validator
            snandula

            I am using graph validator because i am doing cross field validation as well on the object. With JSF2 if i want to use Hibernate validator and perform cross field validation, i see that graph validator is the only way to go or use SEAM. We are already using webflow for navigation, so i am not sure SEAM can be used in that context.

             

            I am trying to read carefully how graph validator works and it could be this.

             

            Graph validator validates all the fields first using Bean validator. If any of the values are not validated. it throws an error. Once those errors are corrected, it probably does the object validation at that poing and all my @AssertTrue annotated methods will be validated. Am i right to think like that?

             

            Even if  the  implementation is to work as i assume above, i am having issues with the validate value method. I have 2 buttons on the same page which require different validation groups. i am able to assign validation groups correctly to the graph validator based on the button click. But the validation messages i see on my page are not consistent every time i click the button. Sometimes 4 messages show up with validation errors. If i click the same button again, this time, i get only one message. Same groups are being validated, but validations are different. I am not sure why this happens.

             

            Here is my code. Hopefully it can be understood.

             

             

            <rich:popupPanel id="caregiverStipendPanel" autosized="true"

                            width="450">

                            <f:facet name="header">

                                <h:outputText value="Edit Stipend" />

                            </f:facet>

                            <h:form id="form2">

                                <rich:messages style="color:red;"></rich:messages>

                                <h:messages />

                                <rich:graphValidator value="#{currentItem}"

                                    groups="#{currentItem.validationGroups}">

                                    <a4j:outputPanel ajaxRendered="true">

                                        <h:panelGroup rendered="#{currentItem.newStipend == true}">

                                            <h:panelGrid columns="2" columnClasses="colStyle1,colStyle2"

                                                rowClasses="rowStyle">

                                                <h:outputText value="Begin Date" />

                                                <rich:calendar value="#{currentItem.beginDate}" />

             

                                                <h:outputText value="End Date" />

                                                <rich:calendar value="#{currentItem.endDate}" />

             

                                                <h:outputText value="Stipend Amount" />

                                                <h:inputText value="#{currentItem.amount}" />

             

                                                <h:outputText value="Payment Type" />

                                                <h:selectOneMenu value="#{currentItem.paymentType}">

                                                    <f:selectItem itemValue="1" itemLabel="EFT" />

                                                    <f:selectItem itemValue="2" itemLabel="Check" />

                                                    <f:ajax execute="form2" render="form2"></f:ajax>

                                                </h:selectOneMenu>

                                            </h:panelGrid>

                                        </h:panelGroup>

             

                                        <h:panelGroup rendered="#{currentItem.newStipend == false}">

                                            <h:panelGrid columns="2" columnClasses="colStyle1,colStyle2"

                                                rowClasses="rowStyle">

                                                <h:outputText value="Begin Date" />

                                                <h:outputText value="#{currentItem.beginDate}">

                                                    <f:convertDateTime pattern="MM-dd-yyyy" />

                                                </h:outputText>

             

                                                <h:outputText value="End Date" />

                                                <rich:calendar value="#{currentItem.endDate}" />

             

                                                <h:outputText value="Stipend Amount" />

                                                <h:outputText value="#{currentItem.amount}" />

             

                                                <h:outputText value="Payment Type" />

                                                <h:selectOneMenu value="#{currentItem.paymentType}">

                                                    <f:selectItem itemValue="1" itemLabel="EFT" />

                                                    <f:selectItem itemValue="2" itemLabel="Check" />

                                                    <f:ajax execute="form2" render="form2"></f:ajax>

                                                </h:selectOneMenu>

                                            </h:panelGrid>

                                        </h:panelGroup>

             

                                        <h:panelGroup rendered="#{currentItem.paymentType == 1}">

                                            <h:panelGrid columns="2" columnClasses="colStyle1,colStyle2"

                                                rowClasses="rowStyle">

             

                                                <h:outputText value="Routing Number" />

                                                <h:panelGroup>

                                                    <h:inputText value="#{currentItem.routingNumber}" />

                                                   <a4j:commandButton style="width:50px" value="Details"

                                                        action="getBankDetails" execute="form2" render="form2">

                                                        <a4j:ajax event="click" immediate="true"

                                                            listener="#{currentItem.setRoutingNumberValidationGroups}" />

                                                    </a4j:commandButton>

                                                </h:panelGroup>

                                                <h:outputText value="Bank Name" />

                                                <h:inputText value="#{currentItem.bankName}" />

                                                <h:outputText value="Account Number" />

                                                <h:inputText value="#{currentItem.accountNumber}" />

                                                <h:outputText value="Account Type" />

                                                <h:inputText value="#{currentItem.accountType}" />

                                            </h:panelGrid>

                                        </h:panelGroup>

                                        <h:panelGroup rendered="#{currentItem.paymentType == 2}">

                                            <h:panelGrid columns="2" columnClasses="colStyle1,colStyle2"

                                                rowClasses="rowStyle">

                                                <h:outputText value="Address1" />

                                                <h:inputText value="#{currentItem.address1}" />

                                                <h:outputText value="Address2" />

                                                <h:inputText value="#{currentItem.address2}" />

                                                <h:outputText value="City" />

                                                <h:inputText value="#{currentItem.city}" />

                                                <h:outputText value="State" />

                                                <h:inputText value="#{currentItem.state}" />

                                                <h:outputText value="Zipcode" />

                                                <h:inputText value="#{currentItem.zipCode}" />

                                            </h:panelGrid>

                                        </h:panelGroup>

                                    </a4j:outputPanel>

                                    <br />

                                    <h:panelGrid>

                                        <h:panelGroup style="width:100%;margin-left:50%;margin-right:50%">

             

                                            <a4j:commandButton style="width:50px" value="OK"

                                                action="addStipend" execute="form2" render="form2"

                                                oncomplete="if(#{facesContext.maximumSeverity == null})

                                                           #{rich:component('caregiverStipendPanel')}.hide();" >

                                                       <a4j:ajax event="click" immediate="true"

                                                listener="#{currentItem.setCaregiverStipendValidationGroups}" />

                                            </a4j:commandButton>

             

                                            <a4j:commandButton style="width:50px" value="Cancel"

                                                immediate="true"

                                                oncomplete="#{rich:component('caregiverStipendPanel')}.hide();" />

                                        </h:panelGroup>

                                    </h:panelGrid>

                                </rich:graphValidator>

                            </h:form>

                        </rich:popupPanel>

             

            The Section identified in BOLD are the 2 button actions. I am updating the validation groups on button click. This works fine. I can see that the validator is using the right groups.

             

            My java code for the currentItem defined above.

             

             

            package gov.va.vba.ui.vo;

             

            import gov.va.vba.ui.faces.validator.groups.CaregiverStipendValidation;

            import gov.va.vba.ui.faces.validator.groups.RoutingNumberValidation;

             

            import java.io.Serializable;

            import java.util.Date;

            import javax.validation.constraints.AssertTrue;

            import javax.validation.constraints.Future;

            import javax.validation.constraints.NotNull;

             

            import org.apache.commons.lang.StringUtils;

             

             

            public class CaregiverStipend implements Serializable,Cloneable{

               

               

                public CaregiverStipend(){

                   

                }

               

               

                private Date createdDate;

               

                @NotNull(groups={CaregiverStipendValidation.class}, message = "Begin Date cannot be null")

                @Future(groups={CaregiverStipendValidation.class}, message = "Begin Date must be in the future")

                private Date beginDate;

               

                @Override

                public Object clone() throws CloneNotSupportedException {

                    Object cloneObject =  super.clone();

                    return cloneObject;

                }

             

                @NotNull(groups={CaregiverStipendValidation.class}, message = "End Date cannot be null")

                @Future(groups={CaregiverStipendValidation.class}, message = "End Date must be in the future")

                private Date endDate;

               

               

                @NotNull(groups={CaregiverStipendValidation.class}, message = "Stipend Amount cannot be null")

                private Double amount;

               

               

                private int paymentType;

               

                @NotNull(groups={RoutingNumberValidation.class,CaregiverStipendValidation.class},message = "Routing number cannot be null")

                private String routingNumber;

               

                private String bankName;

               

                private String accountType;

               

                private String accountNumber;

               

                private String address1;

               

                private String address2;

               

                private String city;

               

                private String state;

               

                private String zipCode;

               

                private int status;

               

                private boolean newStipend;

               

                private Class[] validationGroups;

               

                public void setRoutingNumberValidationGroups(){

                    this.validationGroups = null;

                    this.validationGroups = new Class[]{RoutingNumberValidation.class};

                }

               

                public void setCaregiverStipendValidationGroups(){

                    this.validationGroups = null;

                    this.validationGroups = new Class[]{CaregiverStipendValidation.class,RoutingNumberValidation.class};

                }

               

             

                public Class[] getValidationGroups() {

                    return validationGroups;

                }

             

                /*public void setValidationGroups(Class[] validationGroups) {

                    this.validationGroups = validationGroups;

                }*/

             

                @AssertTrue(groups={CaregiverStipendValidation.class},message="End Date should be greater than begin date")

                public boolean isDatesValid(){

                    return beginDate != null && endDate != null && endDate.before(beginDate);

                }

               

                @AssertTrue(groups={RoutingNumberValidation.class}, message = "Invalid Routing Number")

                public boolean isRoutingNumberValid(){

                        if(paymentType == 1){

                            return !StringUtils.isEmpty(routingNumber) && routingNumber.length() == 9;

                        }

                    return true;

                   

                }

               

                @AssertTrue(groups=(CaregiverStipendValidation.class), message = "Invalid Bank Name")

                public boolean isBankNameValid(){

                    if(paymentType == 1){

                        return !StringUtils.isEmpty(bankName);

                    }

                    return true;

                   

                }

               

                @AssertTrue(groups = (CaregiverStipendValidation.class), message = "Invalid Account Number")

                public boolean isAccountNumberValid(){

                    if(paymentType == 1){

                        return !StringUtils.isEmpty(accountNumber);

                    }

                    return true;

                   

                }

               

                @AssertTrue(groups = (CaregiverStipendValidation.class) ,message = "Invalid Account Type")

                public boolean isAccountTypeValid(){

                    if(paymentType == 1){

                        return  !StringUtils.isEmpty(accountType);

                    }

                    return true;

                   

                }

               

                @AssertTrue(groups=(CaregiverStipendValidation.class),message = "Invalid Address1")

                public boolean isAddress1Valid(){

                   

                    if(paymentType == 2){

                        return  !StringUtils.isEmpty(address1);

                    }

                    return true;

                   

                }

               

                @AssertTrue(groups=(CaregiverStipendValidation.class), message = "Invalid City")

                public boolean isCityValid(){

                    if(paymentType == 2){

                        return  !StringUtils.isEmpty(this.city);

                    }

                    return true;

                   

                }

               

                @AssertTrue(groups=(CaregiverStipendValidation.class),message = "Invalid State")

                public boolean isStateValid(){

                    if(paymentType == 2){

                        return paymentType == 2 && !StringUtils.isEmpty(state);

                    }

                    return true;

                   

                }

               

                @AssertTrue(groups=(CaregiverStipendValidation.class),message = "Invalid zipcode")

                public boolean isZipCodeValid(){

                    if(paymentType == 2){

                        return paymentType == 2 && !StringUtils.isEmpty(zipCode);

                    }

                    return true;

                }

               

               

                public Double getAmount() {

                    return amount;

                }

                public boolean isNewStipend() {

                    return newStipend;

                }

                public void setNewStipend(boolean newStipend) {

                    this.newStipend = newStipend;

                }

                public Date getCreatedDate() {

                    return createdDate;

                }

                public void setCreatedDate(Date createdDate) {

                    this.createdDate = createdDate;

                }

                public Date getBeginDate() {

                    return beginDate;

                }

                public void setBeginDate(Date beginDate) {

                    this.beginDate = beginDate;

                }

                public Date getEndDate() {

                    return endDate;

                }

                public void setEndDate(Date endDate) {

                    this.endDate = endDate;

                }

                public void setAmount(Double stipendAmount) {

                    this.amount = stipendAmount;

                }

                public int getPaymentType() {

                    return paymentType;

                }

                public void setPaymentType(int paymentType) {

                    this.paymentType = paymentType;

                }

                public String getRoutingNumber() {

                    return routingNumber;

                }

                public void setRoutingNumber(String routingNumber) {

                    this.routingNumber = routingNumber;

                }

                public String getBankName() {

                    return bankName;

                }

                public void setBankName(String bankName) {

                    this.bankName = bankName;

                }

                public String getAccountType() {

                    return accountType;

                }

                public void setAccountType(String accountType) {

                    this.accountType = accountType;

                }

                public String getAccountNumber() {

                    return accountNumber;

                }

                public void setAccountNumber(String accountNumber) {

                    this.accountNumber = accountNumber;

                }

                public String getAddress1() {

                    return address1;

                }

                public void setAddress1(String address1) {

                    this.address1 = address1;

                }

                public String getAddress2() {

                    return address2;

                }

                public void setAddress2(String address2) {

                    this.address2 = address2;

                }

                public String getCity() {

                    return city;

                }

                public void setCity(String city) {

                    this.city = city;

                }

                public String getState() {

                    return state;

                }

                public void setState(String state) {

                    this.state = state;

                }

                public String getZipCode() {

                    return zipCode;

                }

                public void setZipCode(String zipCode) {

                    this.zipCode = zipCode;

                }

               

                public int getStatus() {

                    return status;

                }

                public void setStatus(int status) {

                    this.status = status;

                }

               

                public String getPaymentTypeString(){

                    return paymentType == 1?"EFT":"Check";

                }

               

               

            //    public Class[] getGroups() {

            //        return groups;

            //    }

            //

            //    public void setGroups(Class[] groups) {

            //        this.groups = groups;

            //    }

             

                public String getPaymentAddressString1(){

                    StringBuilder s = new StringBuilder();

                    if(paymentType == 1){

                        s.append("Routing Number: ");

                        s.append(routingNumber);

                        s.append("\n");

                        s.append("Bank Name: ");

                        s.append(bankName);

                        s.append("\n");

                        s.append("Account Type: ");

                        s.append(accountType);

                        s.append("\n");

                        s.append("Account Number :");

                        s.append(accountNumber);

                    }else{

                        s.append(address1);

                        s.append("\n");

                        s.append(address2);

                        s.append("\n");

                        s.append(city);

                        s.append("\n");

                        s.append(state);

                        s.append(zipCode);

                    }

                   

                    return s.toString();

                }

               

                public String getPaymentAddressString(){

                    StringBuilder s = new StringBuilder();

                    if(paymentType == 1){

                        s.append("Routing Number: ");

                        s.append(routingNumber);

                        s.append("<br />");

                        s.append("Bank Name: ");

                        s.append(bankName);

                        s.append("<br />");

                        s.append("Account Type: ");

                        s.append(accountType);

                        s.append("<br />");

                        s.append("Account Number :");

                        s.append(accountNumber);

                    }else{

                        s.append(address1);

                        s.append("<br />");

                        s.append(address2);

                        s.append("<br />");

                        s.append(city);

                        s.append("<br />");

                        s.append(state);

                        s.append(zipCode);

                    }

                   

                    return s.toString();

                }

               

                //&lt;br /&gt;   

               

            }

             

            When i click the "Details" only the routing number field should be validated. For this i created the RoutingNumberValidation group.

            When i click the "OK" Button all the fields should be validated. For this i created the CaregiverStipendValidation group.

             

            This is how it works.

             

            1. I Click the Details button, only the routing number field gets validated and i get that validation message. (Routing number is invalid)

            2. I do not correct the error, but immediately click the OK button. I get 4 validation messages. on the dates, routing number and bank name. None of the assert true methods are validated at this time

            3. i still do not correct the error, but click the OK button again. This time, i only get one message saying End Date is invalid.

             

            In both cases 2 and 3 i already confirmed that the group being used is the CargiverStipendValidation. Why am i getting 4 validation messages one time and 1 validation message the other time, when i click the same button? This is my problem. For all the above invocations the validate method on the GraphValidator is being invoked. Not the validateGraph method.

             

            I hope i make sense.