简体   繁体   中英

How to show only one validation error message for multiple rows in JSR 303 with spring?

There is a grid which has multiple rows. Each row has the two same text fields. I am using JSR 303 to validate these fields and the validation is happening alright. However the issue is that multiple error messages are being shown(one for each row) which is not desirable. Is there a way to display only one error message per field for all the rows?

public ModelAndView insert(@Valid @ModelAttribute("proposalwiseselectionform")ProposalWiseSelectionForm proposalwiseselectionformobj,
                               BindingResult result,
                               HttpServletRequest request, HttpServletResponse response) {
        if (result.hasErrors()) {
            if (formBeanObj == null) {
                formBeanObj = proposalwiseselectionformobj;
            }
            mav = new ModelAndView("proposalwiseselection");

            mav.addObject("proposalwiseselectionform", formBeanObj);
        }
    }




public class ProposalWiseSelectionForm {
private String txtLineOfBusiness;
private String txtProduct;
private String btn;
private String clickedGo="N";   
private List arrLineOfBusiness=new ArrayList();
private List arrProduct=new ArrayList();
@Valid
private ArrayList documentList=initiateDocumentList();
private String txtPageMode="I";
private String enableDiscardBtn="N";
private String enableInsertBtn="N";

public ArrayList initiateDocumentList(){
    ArrayList arr=new ArrayList();
    for(int i=0; i<1;i++){
      arr.add(new ProposalWiseSelectionChildForm(i));
    }
    return arr;
  }
}



public class ProposalWiseSelectionChildForm {

private String numProposalWiseSelection;        
private String txtTransactionType;
private String txtTransactionTypeCode;  

@NotEmpty(message="Transaction Type cannot be empty")
private String txtTransactionDesc;

@NotEmpty(message="Document Type cannot be empty")
private String txtPolicyDocument;
private String ynChkBox="0";

}

JSP snippets are as follows,

form:form action="/proposalwiseselection" commandName="proposalwiseselectionform" method="POST" id="proposalwiseselection"/  
form:errors path="*" cssClass="errorblock" element="div"/
form:input path="documentList[${docStatus.index}].txtTransactionDesc"  cssClass="noneditableinputbox" size="40" onkeydown="transactionTypeLOV(event.keyCode,this)" readonly="true" title="Press F2 to get transaction type list" /
form:hidden path="documentList[${docStatus.index}].txtTransactionTypeCode"/
form:input path="documentList[${docStatus.index}].txtPolicyDocument"  cssClass="noneditableinputbox" size="40"  readonly="true"/
form:hidden path="documentList[${docStatus.index}].numPolicyDocumentCode"/

Although the following solution is very crude, it however performs the functionality you need. You can easily work make a more readable and adhere to the Spring principals, but I just whipped this up to show how something like what you are asking can be done.

First of all you need to first obtain a Validator from Spring.

@Autowired
Validaror validator;

Next you need to remove the @Valid annotation and perform the validation on your own.

That means that your method would look like this:

public ModelAndView insert(@ModelAttribute("proposalwiseselectionform")ProposalWiseSelectionForm proposalwiseselectionformobj,
                               BindingResult result,
                               HttpServletRequest request, HttpServletResponse response)

{
        validate(bindingResult);
        if (result.hasErrors()) {
            if (formBeanObj == null) {
                formBeanObj = proposalwiseselectionformobj;
            }
            mav = new ModelAndView("proposalwiseselection");

            mav.addObject("proposalwiseselectionform", formBeanObj);
        }
}

Finally the validate method would look like this:

private void validate(BindingResult bindingResult) {

    final BindingResult intermediateBindingResult = new BeanPropertyBindingResult(bindingResult.getTarget(), bindingResult.getObjectName()) ;
    validator.validate(bindingResult.getTarget(), intermediateBindingResult);

    final List<FieldError> originalFieldErrors = intermediateBindingResult.getFieldErrors();
    final Set<String> alreadyAddedFieldNames = new HashSet<>();
    final List<FieldError> distinctFieldErrors = new ArrayList<>();
    for (FieldError fieldError : originalFieldErrors) {
        if(alreadyAddedFieldNames.contains(fieldError.getField())) {
            continue;
        }

        distinctFieldErrors.add(fieldError);
        alreadyAddedFieldNames.add(fieldError.getField());
    }

    for (FieldError distinctFieldError : distinctFieldErrors) {
        bindingResult.addError(distinctFieldError);
    }
}

What the code above does is store the regular validation into an intermediate binding result, and the loop over all the FieldError and adds only the first one per field.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM