Home

News

Download (SourceForge Hosted)

Documentation

Articles

Feedback

Advanced Usage Guide

Introduction

iScreen, though fairly simple, has a great deal of power because of its flexibility and reliance upon OGNL. The configuration file is powerful enough to be used to do some very interesting things, though it can be fairly complex to deal with, sometimes. This guide's purpose is to show some more advanced examples of how iScreen can be used and configured.

Validating Object Graphs

In general, validation engines are designed to validate individual Java objects. However, it's common to have an entire object graph that needs validating. This capability is possible using iScreen's validation set forwarding capability.

For this example, we'll use a simple object graph. First, the parent object will be Person, which is defined like this:

public class Person { private Address address; private String firstName; private String lastName; public Person() {} public Address getAddress() { return address; } //end getAddress() public void setAddress( Address theAddress ) { } //end setAddress() ... } //end Person

As you can see, the Person object contains an Address object. It's defined as follows:

public class Address { private String line1; private String line2; private String city; private State state; private String zip; public Address() {} public State getState() { return state; } //end getState() public void setState( State theState ) { state = theState; } //end setState() ... }

From the above, assume that the contained State is just an enumerated type.

For this example, let's define the "rules" of the validations in simple english:

  • A Person *might* have an address (that is, it can be null)
  • If the address is not null, it should be validated.
  • The first name is not required, but if it's there, is shouldn't be longer than 10 characters.
  • The last name is required, must be at least one character long, but no longer than 20 characters.
  • For the address, the only required field (if the address is not null) is the State.

From these rules, the configuration file for this example would be:

<?xml version="1.0" encoding="utf-8"?> <validation-root namespace="my.namespace"> <include file="org/iscreen/validators.xml" /> <!-- Validation set for the PERSON object. --> <validation-set id="Person"> <!-- Validation for the First Name field. --> <use-validator ref="org.iscreen.StringValidator"> <mapping from="firstName" /> <label>First Name</label> <constraint property="maxLength">10</constraint> </use-validator> <!-- Validation for the Last Name field. --> <use-validator ref="org.iscreen.StringValidator"> <mapping from="lastName" /> <label>Last Name</label> <constraint property="minLength">1</constraint> <constraint property="maxLength">20</constraint> </use-validator> <use-validation-set ref="Address" if="address != null" map="address" /> </validation-set> <!-- Validation set for the ADDRESS object. --> <validation-set id="Address"> <!-- Validation for the State field. --> <use-validator ref="org.iscreen.NullValidator"> <mapping from="state" /> <label>State</label> </use-validator> </validation-set> </validation-root>

There are a few interesting aspects of the example above. First, there's the usage of the 'use-validation-set' element, which "forwards" or includes another validation set as part of the parent validation set. This is useful when validating object graphs (though not technically necessary, since you could embed the Address validation set within the Person validation set, but you wouldn't be able to reuse it like you can if you include it).

There are a couple of attributes that are part of that forwarding that are of interest. First, there's the 'if' attribute. The 'if' attribute is used as a condition check to see whether to forward to the child validation set or not. It's an OGNL expression using the Java instance being validated by the validation set. Since it's a conditional, it must convert to a boolean value. In this case, a comparison between the address property and null dictates whether the address property is validated. This approach is used because our "rules" dictated that the address could be null. If the rule defined that the address must not be null, then a different approach would be taken.

In addition to the 'if' attribute is the 'map' attribute. This uses an OGNL expression to map a property from the Java instance being validated to the Java object that the forwarded validation set will actually validate (it will have no knowledge of the parent Java instance). By default, the 'map' attribute, if not specified, is #root, which is an OGNL identity expression, which forwards the whole Java instance, itself.

What about the scenario where the requirement for an address property is made strict? That is, what if it's required and shouldn't be null? Here's the adjusted configuration for that situation:

<?xml version="1.0" encoding="utf-8"?> <validation-root namespace="my.namespace"> <include file="org/iscreen/validators.xml" /> <!-- Validation set for the PERSON object. --> <validation-set id="Person"> <!-- Validation for the First Name field. --> <use-validator ref="org.iscreen.StringValidator"> <mapping from="firstName" /> <label>First Name</label> <constraint property="maxLength">10</constraint> </use-validator> <!-- Validation for the Last Name field. --> <use-validator ref="org.iscreen.StringValidator"> <mapping from="lastName" /> <label>Last Name</label> <constraint property="minLength">1</constraint> <constraint property="maxLength">20</constraint> </use-validator> <!-- Ensure that the address property is not null. --> <use-validator ref="org.iscreen.NullValidator" fail-fast="true"> <mapping from="address" /> <label>Address</label> </use-validator> <use-validation-set ref="Address" map="address" /> </validation-set> <!-- Validation set for the ADDRESS object. --> <validation-set id="Address"> <!-- Validation for the State field. --> <use-validator ref="org.iscreen.NullValidator"> <mapping from="state" /> <label>State</label> </use-validator> </validation-set> </validation-root>

What's the difference? First, we took out the 'if' attribute from the validation set forwarding, because it's unnecessary. Second, we added a null validator check on the address. However, that's not sufficient. On the null validator check, we added the 'fail-fast' attribute and set it to true (it defaults to false). When this is encountered, if the null validator check (or any configured validator, for that matter) fails (reports a failure), then no further validations within the validation set are performed (and the forwarding to another validation set is included in this prohibition).

As an additional note, this property (fail-fast) could also be used on the use-validation-set element, as well, in which case, any failure within the included validation set would cause the parent validation set to stop validating (though it would report any failures it or the forwarded validation set had).