Terry, Thanks for asking the question - I've asked a similar question in the past. I did not realize that validator has some collection support, I may look further into that.
I used a different approach by putting together a little "glue" code in my main form bean's "validate" method. For example, I have a composite form bean that has properties for a "base" form bean and two collections of multiple "line item" form beans. Both the base and line item form beans have their own validator validations. Below is an example. Note that I have to lookup the ActionMapping for a "utility" action that uses the line item form to update a single line item. I would go with Mark's idea if it works for you - much less manual glue code, but at least this reuses your validations. - Richard public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) { // Let standard validation run first. ActionErrors errors = null; // errors = super.validate(mapping, request); ActionError error = null; ActionErrors currLineItemsErrors = null; ActionErrors newLineItemsErrors = null; if (errors == null) errors = new ActionErrors(); LineItemForm li = null; ActionMapping liMapping = (ActionMapping)mapping.getModuleConfig().findActionConfig("/config/LineItemA ction"); // Check each new currLineItems formbean if (newLineItems != null && newLineItems.size() > 0) { if (log.isDebugEnabled()) log.debug("Validate - count of newLineItems="+newLineItems.size()); for (int i = 0; i < newLineItems.size(); i++) { // Do not consider if some part of form is not filled in if ( newLineItems.get(i) == null ) { if (log.isDebugEnabled()) log.debug("Validate - newLineItem["+i+"] is null, skipping."); continue; } li = (LineItemForm)newLineItems.get(i); if (log.isDebugEnabled()) log.debug("Validate - newLineItem["+i+"]='"+li+"'"); if ( li.isEmpty() ) { if (log.isDebugEnabled()) log.debug("Validate - newLineItem["+i+"] is empty, skipping."); continue; } li.setServlet(getServlet()); newLineItemsErrors = li.validate(liMapping,request); if (!newLineItemsErrors.isEmpty()) { errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("error.in.new.line.num", Integer.toString(i+1))); errors.add(newLineItemsErrors); } } } if (currLineItems != null && currLineItems.size() > 0) { if (log.isDebugEnabled()) log.debug("Validate - count of currLineItems="+currLineItems.size()); for (int i = 0; i < currLineItems.size(); i++) { // Do not consider if some part of form is not filled in if ( currLineItems.get(i) == null ) { if (log.isDebugEnabled()) log.debug("Validate - currLineItem["+i+"] is null, skipping."); errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("error.in.curr.line.num", Integer.toString(i+1))); errors.add(currLineItemsErrors); continue; } li = (LineItemForm)currLineItems.get(i); if (log.isDebugEnabled()) log.debug("Validate - currLineItem["+i+"]='"+li+"'"); if ( li.isEmpty() ) { if (log.isDebugEnabled()) log.debug("Validate - currLineItem["+i+"] is empty, skipping."); errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("error.in.curr.line.num", Integer.toString(i+1))); errors.add(currLineItemsErrors); continue; } li.setServlet(getServlet()); currLineItemsErrors = li.validate(liMapping,request); if (!currLineItemsErrors.isEmpty()) { errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("error.in.curr.line.num", Integer.toString(i+1))); errors.add(currLineItemsErrors); } } } return errors; } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]