Stripes

Nested validation errors reported when validating a null or zero length map.

Details

  • Type: Bug Bug
  • Status: Open Open
  • Priority: Major Major
  • Resolution: Unresolved
  • Affects Version/s: Release 1.4.1
  • Fix Version/s: None
  • Component/s: Validation
  • Labels:
    None
  • Environment:
    Windows / Tomcat 5.5

Description

I've been working on a javascript-enabled form that allows you to dynamically add and remove 'rows' in a table, represented by TreeMaps of beans stripes-side:

public TreeMap<Long, ChannelDataBean> getChannels() { return this.channels; }
public void setChannels(TreeMap<Long, ChannelDataBean> channels) { this.channels = channels; }
@ValidateNestedProperties
({ @Validate(field="name", required=true, minlength=3, maxlength=50), @Validate(field="incomingUsername", required=true, minlength=3, maxlength=50), @Validate(field="outgoingUsername", required=true, minlength=3, maxlength=50), @Validate(field="incomingPassword", required=true, minlength=3, maxlength=50), @Validate(field="outgoingPassword", required=true, minlength=3, maxlength=50) })
private TreeMap<Long, ChannelDataBean> channels;

and their appropriate inputs, generated by reflection, page side.

It works great – unless you try and submit a form with no elements at all. In this case, Stripes reports validation errors for every single bean property described in the corresponding nested @Validate annotation.

Is there a work-around for this, aside from implementing a ValidationErrorHandler (I kind of want the solution to be totally portable and generic, which it is currently), or is this a bug.

Cheers

Si

PS: I love stripes, it's seriously excellent. Cheers for the terrific framework.

Activity

Hide
Tim Fennell added a comment - 08/Nov/06 9:06 AM

I'd say this is a bug. The whole idea is that for indexed properties only those indexes that have some values get validated. The reason this is happening is because the detection of when a property is indexed is based on there being indexed style keys in the request. I think all I'd need to do is alter this to actually inspect the bean and see if a property is indexed instead.

Show
Tim Fennell added a comment - 08/Nov/06 9:06 AM I'd say this is a bug. The whole idea is that for indexed properties only those indexes that have some values get validated. The reason this is happening is because the detection of when a property is indexed is based on there being indexed style keys in the request. I think all I'd need to do is alter this to actually inspect the bean and see if a property is indexed instead.
Hide
Iwao AVE! added a comment - 14/Mar/07 11:43 PM

I needed to solve this problem for my project and made a patch.
It skips required validation when the property is 1) indexed and 2) not included in the request parameters.

===================================================================
— src/net/sourceforge/stripes/controller/DefaultActionBeanPropertyBinder.java(revision 486)
+++ src/net/sourceforge/stripes/controller/DefaultActionBeanPropertyBinder.java(working copy)
@@ -555,9 +555,23 @@
// Make the added check that if the form is a wizard, the required field is
// in the set of fields that were on the page
if (!wizard || fieldsOnPage.contains(propertyName)) {

  • String[] values = bean.getContext().getRequest().getParameterValues(propertyName);
  • log.debug("Checking required field: ", propertyName, ", with values: ", values);
  • checkSingleRequiredField(propertyName, propertyName, values, req, errors);
    + // Check if the required field is indexed
    + PropertyExpression propExpr = PropertyExpression.getExpression(propertyName);
    + PropertyExpressionEvaluation propEval = new PropertyExpressionEvaluation(propExpr, bean);
    + boolean isIndexed = false;
    + for (NodeEvaluation nodeEval = propEval.getRootNode(); nodeEval != null && !isIndexed;
    + nodeEval = nodeEval.getNext())
    + { + NodeType nodeType = nodeEval.getType(); + isIndexed = NodeType.ListEntry.equals(nodeType) + || NodeType.MapEntry.equals(nodeType) + || NodeType.ArrayEntry.equals(nodeType); + }
    + if (!isIndexed) { + String[] values = bean.getContext().getRequest().getParameterValues(propertyName); + log.debug("Checking required field: ", propertyName, ", with values: ", values); + checkSingleRequiredField(propertyName, propertyName, values, req, errors); + }
    }
    }
    }

There seemed to be several ways to detect if the property is indexed or not.
I used NodeType to do this but it might not be the most efficient way.
If someone knows a better way, please let me know.

Show
Iwao AVE! added a comment - 14/Mar/07 11:43 PM I needed to solve this problem for my project and made a patch. It skips required validation when the property is 1) indexed and 2) not included in the request parameters. =================================================================== — src/net/sourceforge/stripes/controller/DefaultActionBeanPropertyBinder.java(revision 486) +++ src/net/sourceforge/stripes/controller/DefaultActionBeanPropertyBinder.java(working copy) @@ -555,9 +555,23 @@ // Make the added check that if the form is a wizard, the required field is // in the set of fields that were on the page if (!wizard || fieldsOnPage.contains(propertyName)) {
  • String[] values = bean.getContext().getRequest().getParameterValues(propertyName);
  • log.debug("Checking required field: ", propertyName, ", with values: ", values);
  • checkSingleRequiredField(propertyName, propertyName, values, req, errors); + // Check if the required field is indexed + PropertyExpression propExpr = PropertyExpression.getExpression(propertyName); + PropertyExpressionEvaluation propEval = new PropertyExpressionEvaluation(propExpr, bean); + boolean isIndexed = false; + for (NodeEvaluation nodeEval = propEval.getRootNode(); nodeEval != null && !isIndexed; + nodeEval = nodeEval.getNext()) + { + NodeType nodeType = nodeEval.getType(); + isIndexed = NodeType.ListEntry.equals(nodeType) + || NodeType.MapEntry.equals(nodeType) + || NodeType.ArrayEntry.equals(nodeType); + } + if (!isIndexed) { + String[] values = bean.getContext().getRequest().getParameterValues(propertyName); + log.debug("Checking required field: ", propertyName, ", with values: ", values); + checkSingleRequiredField(propertyName, propertyName, values, req, errors); + } } } }
There seemed to be several ways to detect if the property is indexed or not. I used NodeType to do this but it might not be the most efficient way. If someone knows a better way, please let me know.
Hide
Karel Kolman added a comment - 24/May/07 2:18 AM

I'd love to be able to set min and max number of elements allowed in an indexed property.

Using the example from the documentation:

@ValidateNestedProperties(
@Validate(field="phoneNumber", required=true),
@Validate(field="pets", minsize=0, maxsize=10),
@Validate(field="pets.age", required=true, maxvalue=100),
@Validate(field="pets.nicknames.name", required=true, maxlength=50)
)
private Person person;

The pets collection has minsize set to 0 - the last two validation rules are skipped when a form with no pets specified is submitted.

If minsize was set to 1, at least one pet would have to be assigned to a person.

Show
Karel Kolman added a comment - 24/May/07 2:18 AM I'd love to be able to set min and max number of elements allowed in an indexed property. Using the example from the documentation: @ValidateNestedProperties( @Validate(field="phoneNumber", required=true), @Validate(field="pets", minsize=0, maxsize=10), @Validate(field="pets.age", required=true, maxvalue=100), @Validate(field="pets.nicknames.name", required=true, maxlength=50) ) private Person person; The pets collection has minsize set to 0 - the last two validation rules are skipped when a form with no pets specified is submitted. If minsize was set to 1, at least one pet would have to be assigned to a person.

People

Vote (3)
Watch (3)

Dates

  • Created:
    08/Nov/06 8:04 AM
    Updated:
    19/Jan/08 2:47 PM