Spring Modules Validation

11
12/14/11 Spring Modules Validation 1/11 springb\e[ample.org/e[amples/spring-modules-validation-module.html Prev Ne[t SpUing ModXleV ValidaWion DaYid Winterfeldt 2009 TKH SSULQJ MRGXOHV SURMHFW KDV D QXPEHU RI VXESURMHFWV, LQFOXGLQJ YDOLGDWLRQ. TKLV PRGXOH LV EDVHG RQ SSULQJ MRGXOHV VDOLGDWLRQ VHU VLRQ 0.9 DQG KDV D QXPEHU RI HQKDQFHPHQWV WR WKH VDODQJ SDUW RI WKH SURMHFW. POHDVH UHIHU WR WKH RULJLQDO GRFXPHQWDWLRQ IRU DGGLWLRQDO LQIRUPDWLRQ VLQFH WKLV VHFWLRQ ZLOO SULPDULO\ IRFXV RQ H[SODLQLQJ VDODQJ DQG WKH HQKDQFHPHQWV TKDQNV WR HYHU\RQH WKDW KDV ZRUNHG RQ WKLV SURMHFW SUHYLRXVO\ DQG FXUUHQWO\. 1. Valang VDODQJ L V VKRUW IRU Va-lidation LaQg-uage. IW SURYLGHV D YHU\ UHDGDEOH ODQJXDJH IRU H[SUHVVLQJ YDOLGDWLRQ UXOHV, DV ZHOO DV SURYLGLQJ WKH DELOLW\ WR DGG FXVWRP IXQFWLRQV WR WKH ODQJXDJH. OQFH WKH ValangValidaWoU LV FRQILJXUHG, XVLQJ LW LVQ'W GLIIHUHQW WKDQ DQ\ RWKHU SSULQJ VDOLGDWRU VLQFH LW LPSOHPHQWV oUg.VpUingfUameZoUk.YalidaWion. ValidaWoU . BHORZ LV D OLVW RI FXUUHQW HQKDQFHPHQWV. VHU VLRQ 0.91 B\WHFRGH JHQHUDWLRQ DGGHG WR DHIDXOWVL VLWRU DV D UHSODFHPHQW IRU UHIOHFWLRQ DFFHVVLQJ VLPSOH SURSHUWLHV (BHDQPURSHUW\FXQFWLRQ) IRU D VLJQLILFDQW SHUIRUPDQFH LPSURYHPHQW. BDVLF HQXP FRPSDULVRQ VXSSRUW. IQ WKH H[SUHVVLRQ EHORZ WKH SHUVRQT\SH LV DQ HQXP DQG WKH YDOXH STUDENT ZLOO EH FRQYHUHWHG WR DQ HQXP IRU FRPSDULVRQ. TKH YDOXH PXVW PDWFK DQ HQXP YDOXH RQ WKH W\SH EHLQJ FRPSDUHG RU DQ H[FHSWLRQ ZLOO EH WKURZQ. peUVonT\pe EQ UALS ['STUDENT'] FRU EHWWHU SHUIRUPDQFH WKH IXOO FODVV QDPH FDQ EH VSHFLILHG VR WKH HQXP FDQ EH UHWULHYHG GXULQJ SDUVLQJ. TKH ILUVW H[DPSOH LV IRU VWDQGDUG HQXP DQG WKH VHFRQG RQH LV IRU DQ LQQHU HQXP FODVV . peUVonT\pe EQ UALS ['o Ug.VpUingmodXleV.YalidaWion.e[ample.PeUVonT\pe.ST UDENT'] peUVonT\pe EQ UALS ['o Ug.VpUingmodXleV.YalidaWion.e[ample.PeUVon$PeUVonT\pe.ST UDENT'] WKHUH FODXVH VXSSRU W. IQ WKH H[SUHVVLRQ EHORZ, WKH SDUW RI WKH H[SUHVVLRQ pUice < 100 ZLOO RQO\ EH HYDOXDWHG LI WKH peUVonT\pe LV 'STUDENT'. OWKHUZLVH WKH YDOLGDWLRQ ZLOO EH VNLSSHG. pUice < 100 WHERE peUVonT\pe EQ UALS ['STUDENT'] IPSURYHG SHU IRUPDQFH RI 'IN'/'NOT IN' L I FRPSDULQJ D YDOXH WR D MDYD.XWLO.SHW LW ZLOO XVH SHW.FRQWDLQV(YDOXH). SWDWLF OLVWV RI SWULQJV (H[: 'A', 'B', 'C') DUH QRZ VWRUHG LQ D SHW LQVWHDG RI DQ AUUD\LLVW. FXQFWLRQV FDQ EH FRQILJXUHG LQ SSULQJ, EXW QHHG WR KDYH WKHLU VFRSH VHW DV SURWRW\SH DQG XVH D FXQFWLRQWUDSSHU WKDW LV DOVR D SURWRW\SH EHDQ ZLWK <aop:scoped-pro[\> VHW RQ LW. RHPRYHG VHUYOHW GHSHQGHQF\ IURP VDODQJ SURMHFW H[FHSW IRU WKH FXVWRP JSP WDJ VDODQJVDOLGDWHTDJ QHHGLQJ LW, EXW UXQQLQJ VDODQJ QR ORQJHU UHTXLUHV LW. TKLV LQYROYHG Spring b\ E[ample Part VII. Modules Spring Modules Validation

Transcript of Spring Modules Validation

Page 1: Spring Modules Validation

12/14/11 Spring Modules Validation

1/11springbyexample.org/examples/spring-modules-validation-module.html

Prev Next

Spring Modules Validation

David Winterfeldt

2009

The Spring Modules project has a number of subprojects, including validation. This module isbased on Spring Modules Validation Version 0.9 and has a number of enhancements to theValang part of the project. Please refer to the original documentation for additional informationsince this section will primarily focus on explaining Valang and the enhancements

Thanks to everyone that has worked on this project previously and currently.

1. Valang

Valang is short for Va-lidation Lang-uage. It provides a very readable language for expressingvalidation rules, as well as providing the ability to add custom functions to the language. Oncethe V a l a n g V a l i d a t o r is configured, using it isn't different than any other Spring Validator since itimplements o r g . s p r i n g f r a m e w o r k . v a l i d a t i o n . V a l i d a t o r .

Below is a list of current enhancements.

Version 0.91

Bytecode generation added to DefaultVisitor as a replacement for reflection accessingsimple properties (BeanPropertyFunction) for a significant performance improvement.Basic enum comparison support. In the expression below the personType is an enum andthe value S T U D E N T will be convereted to an enum for comparison. The value must match anenum value on the type being compared or an exception will be thrown.

p e r s o n T y p e E Q U A L S [ ' S T U D E N T ' ]

For better performance the full class name can be specified so the enum can be retrievedduring parsing. The first example is for standard enum and the second one is for an innerenum class .

p e r s o n T y p e E Q U A L S [ ' o r g . s p r i n g m o d u l e s . v a l i d a t i o n . e x a m p l e . P e r s o n T y p e . S T U D E N T ' ]

p e r s o n T y p e E Q U A L S [ ' o r g . s p r i n g m o d u l e s . v a l i d a t i o n . e x a m p l e . P e r s o n $ P e r s o n T y p e . S T U D E N T ' ]

Where clause support. In the expression below, the part of the expression p r i c e < 1 0 0 willonly be evaluated if the p e r s o n T y p e is 'STUDENT'. Otherwise the validation will be skipped.

p r i c e < 1 0 0 W H E R E p e r s o n T y p e E Q U A L S [ ' S T U D E N T ' ]

Improved performance of 'IN'/'NOT IN' if comparing a value to a java.util.Set it will useSet.contains(value). Static lists of Strings (ex: 'A', 'B', 'C') are now stored in a Set insteadof an ArrayList.Functions can be configured in Spring, but need to have their scope set as prototype anduse a FunctionWrapper that is also a prototype bean with <aop:scoped-proxy> set on it.Removed servlet dependency from Valang project except for the custom JSP tag

ValangValidateTag needing it, but running Valang no longer requires it. This involved

Spring by Example

Part VII. ModulesSpring Modules Validation

Page 2: Spring Modules Validation

12/14/11 Spring Modules Validation

2/11springbyexample.org/examples/spring-modules-validation-module.html

ValangValidateTag needing it, but running Valang no longer requires it. This involvedremoving ServletContextAware from it's custom dependency injection. If someone wasusing this in a custom function, the function can now be configured directly in Spring andSpring can inject any "aware" values.Changed logging to use SLF4J api.

Version 0.92

Removed custom dependency injection since functions can be configured in Spring.Added auto-discovery of FunctionWrapper beans from the Spring context to go with existingauto-discovery of FunctionDefinition beans.

Version 0.93

Made specific comparison classes for each operator for a performance improvement.Changed IS WORD and IS BLANK to use Commons Lang StringUtils, which will change thebehavior slightly but should be more accurate to the description of the validation.Change Operator from interfaces to an enum and removed OperatorConstants.Fixed bytecode generation to handle a M a p , a L i s t , and an Array.

Version 0.94

Upgraded to Spring 3.0 and changed group & artifact IDs to match standard Spring namingconventions.

Note

Support for the where clause has not been added to the JavaScript custom tagcurrently.

Rule Syntax

The basic construction of a Valang rule is to have it begin and end with a brace. Within thebraces, the default property name for the rule is specified first. Then the Valang expression,followed by the default error message. These are all the required values for a Valang rule. Theother optional values for a rule are the error message key and arguments for it. Each of thevalues of the rule are delimitted by a colon.

{ <property-name> : <expression> : <default-error-message> : <error-message-key> :<error-message-args> }

Table 1. Rule Syntax

Rule Value Description Required

property-name

This is the default property of the bean being targeted forvalidation, and can be referred to with the shortcut ? in anexpression.

t r u e

expression The Valang expression. t r u e

default-error-message

The default error message. If this isn't needed, it can be left blankeven though it's required.

t r u e

error-message-key

The message resource key for the i18n error message. f a l s e

error-message-arg

If the error-message-key is specified, arguments for the errormessage can also be set as the final value of the rule. This acceptsa comma delimited list of values.

f a l s e

Expression Syntax

The expression language provides an English like syntax for expressing validation rules. Thereare a number of operators for comparing a value to another. Logical expressions, resulting int r u e or f a l s e , can be grouped together with parentheses to form more complex expressions.

Just to give some context to the explanation of all the rules, below is a simple example. The

bean being validated has the properties g e t F i r s t N a m e ( ) , g e t L a s t N a m e ( ) , and g e t A g e ( ) . The first two

Page 3: Spring Modules Validation

12/14/11 Spring Modules Validation

3/11springbyexample.org/examples/spring-modules-validation-module.html

bean being validated has the properties g e t F i r s t N a m e ( ) , g e t L a s t N a m e ( ) , and g e t A g e ( ) . The first tworeturn a S t r i n g and the last returns an i n t . The default property is 'firstName', which is referredto by the question mark. The first part of the rule enclosed in parentheses checks if the firstname is either 'Joe' or it's length is greater than 5. The next part checks if the last name is oneof the values in the list, and the final part checks if the age is over 18.

( ? E Q U A L S ' J o e ' O R l e n g t h ( ? ) > 5 ) A N D l a s t N a m e I N ' J o h n s o n ' , ' J o n e s ' , ' S m i t h ' A N D a g e > 1 8

Operator Syntax

The parser is not case sensitive when processing the operators.

Table 2. Expression Operators

ComparisonOperator

Description Supports Example

= | == | IS |EQUALS

Checks for equality.

Strings,booleans,numbers,dates, andenums.

f i r s t N a m eE Q U A L S ' J o e '

!= | <> | >< | ISNOT | NOT EQUALS

Checks for inequality.

Strings,booleans,numbers,dates, andenums.

f i r s t N a m e N O TE Q U A L S ' J o e '

> | GREATER THAN| IS GREATERTHAN

Checks if a value is greater thananother.

Numbersand dates.

a g e > 1 8

< | LESS THAN | ISLESS THAN

Checks if a value is less than another.Numbersand dates.

a g e > 1 8

>= | => |GREATER THAN OREQUALS | ISGREATER THAN OREQUALS

Checks if a value is greater than orequal to another.

Numbersand dates.

a g e > = 1 8

<= | =< | LESSTHAN OR EQUALS |IS LESS THAN OREQUALS

Checks if a value is less than or equalto another.

Numbersand dates.

a g e < = 1 8

NULL | IS NULL Checks if a value is n u l l . Objects.f i r s t N a m e I SN U L L

NOT NULL | IS NOTNULL

Checks if a value is not n u l l . Objects.f i r s t N a m e I SN O T N U L L

HAS TEXTChecks if the value has at least onenon-whitespace character.

Strings.f i r s t N a m e H A ST E X T

HAS NO TEXTChecks if the value doesn't have anon-whitespace character.

Strings.f i r s t N a m e H A SN O T E X T

HAS LENGTHChecks if the value's length is greaterthan zero.

Strings.f i r s t N a m e H A SL E N G T H

HAS NO LENGTH Checks if the value's length is zero. Strings.f i r s t N a m e H A SN O L E N G T H

IS BLANKChecks if the value is blank (n u l l orzero length). Strings.

f i r s t N a m e I SB L A N K

IS NOT BLANKChecks if the value isn't blank (notn u l l , length greater than zero).

Strings.f i r s t N a m e I SN O T B L A N K

IS UPPERCASE | ISUPPER CASE | ISUPPER

Checks if the value is uppercase. Strings.f i r s t N a m e I SU P P E R C A S E

IS NOT UPPERCASE| IS NOT UPPERCASE | IS NOTUPPER

Checks if the value isn't uppercase. Strings.f i r s t N a m e I SN O T U P P E R C A S E

IS LOWERCASE |IS LOWER CASE |IS LOWER

Checks if the value is lowercase. Strings.f i r s t N a m e I SL O W E R C A S E

IS NOTLOWERCASE | IS

NOT LOWER CASE Checks if the value isn't lowercase. Strings.

f i r s t N a m e I S

N O T L O W E R C A S E

Page 4: Spring Modules Validation

12/14/11 Spring Modules Validation

4/11springbyexample.org/examples/spring-modules-validation-module.html

NOT LOWER CASE| IS NOT LOWER

Checks if the value isn't lowercase. Strings. N O T L O W E R C A S E

IS WORDChecks if the value has one or moreletters or numbers (no spaces orspecial characters).

Strings.f i r s t N a m e I SW O R D

IS NOT WORDChecks if the value doesn't have oneor more letters or numbers (no spacesor special characters).

Strings.f i r s t N a m e I SN O T W O R D

BETWEENChecks if a value is between two othervalues.

Numbersand dates.

a g e B E T W E E N 1 8A N D 6 5

NOT BETWEENChecks if a value isn't between twoother values.

Numbersand dates.

a g e N O T B E T W E E N1 8 A N D 6 5

IN Checks if a value is in a list.

Strings,booleans,numbers,dates, andenums.

f i r s t N a m e I N' J o e ' , ' J a c k ' ,' J a n e ' , ' J i l l '

NOT IN Checks if a value isn't in a list.

Strings,booleans,numbers,dates, andenums.

f i r s t N a m e N O TI N ' J o e ' ,' J a c k ' , ' J a n e ' ,' J i l l '

NOTChecks for the opposite of thefollowing expression.

Anyexpression.

N O T f i r s t N a m eE Q U A L S ' J o e '

!Changes a boolean expression to it'sopposite.

Booleansm a t c h e s ( ' \ \ s + ' ,f i r s t N a m e ) I S !( T R U E )

ANDUsed to join together the logicalcomparisons on either side of theoperator. Both must evaluate to t r u e .

Anyexpression.

f i r s t N a m eE Q U A L S ' J o e 'A N D a g e > 2 1

OR

Used to join together the logicalcomparisons on either side of theoperator. Only one must evaluate tot r u e .

Anyexpression.

f i r s t N a m eE Q U A L S ' J o e ' O Ra g e > 2 1

WHERE

If the where expression is true, thenthe main expression for validation isperformed. Otherwise it isn't evaluatedand no errors are generated.

Anyexpression.

f i r s t N a m eE Q U A L S ' J o e 'W H E R E a g e > 2 1

thisA reference to the bean passed in forvalidation, which could be passed intoa custom function for example.

Anyexpression.

i s V a l i d ( t h i s )I S T R U E

Literal Syntax

Table 3. Literals

LiteralType

Description Example

StringS t r i n g literalsare surroundedby single quotes.

'Joe'

Numbers

Numbers can beexpressedwithout anyspecial syntax.Numbers are allparsed usingB i g D e c i m a l .

1, 100, 0.73, -2.48

Dates

Date literals aresurrounded bybrackets.

These are thesupportedformatssupported by theD e f a u l t D a t e P a r s e r .

yyyyMMdd, yyyy-

[20081230], [2008-12-30], [2008-12-30 12:20:31]

Page 5: Spring Modules Validation

12/14/11 Spring Modules Validation

5/11springbyexample.org/examples/spring-modules-validation-module.html

yyyyMMdd, yyyy-MM-dd, yyyy-MM-dd HH:mm:ss,yyyyMMddHHmmss,yyyyMMddHH:mm:ss, yyyy-MM-dd HHmmss

Booleans

There are fourdifferentconstants forboolean values.The values'TRUE' and 'YES'represent t r u e ,and the values'FALSE' and 'NO'represent f a l s e

TRUE, YES, FALSE, NO

Enums

Enums aresurrounded bybracket andsingle quotes. Ifthe full path tothe enum isn'tspecified, it willbe resolvedwhen theexpression isevaluated bylooking up theenum value fromenum on theopposite side ofthe expression.

['FAIL'], ['org.springmodules.validation.valang.CreditStatus.FAIL'],['org.springmodules.validation.valang.Person$CreditRating.EXCELLENT']

Mathematical Operator Syntax

Valang supports basic mathematical formulas based on numeric literals and property values.

Table 4. Mathematical Expression Operators

Mathematical Operator Description Example

+ Addition operator. p r i c e + 1 2

- Subtraction operator. p r i c e - 1 2

* Multiplication operator. p r i c e * 1 . 2

/ | DIV Division operator. p r i c e / 2

% | MOD Modulo operator. a g e % 1 0

Property Syntax

Valang supports standard property and nested property access to the bean passed in forvalidation.

Table 5. Property Syntax

PropertyType

Description Example

StandardUsing standard JavaBean property notation, a value from thebean being validated may be retrieved. The a d d r e s s representsg e t A d d r e s s ( ) on the bean.

a d d r e s s I S N O TN U L L

Nested

Using standard JavaBean property notation, a nested valuefrom the bean being validated may be retrieved. Thea d d r e s s . c i t y represents g e t A d d r e s s ( ) . g e t C i t y ( ) on the bean.

a d d r e s s . c i t y I SN O T B L A N K

From an array, L i s t , or S e t , a value from it can be returned by

Page 6: Spring Modules Validation

12/14/11 Spring Modules Validation

6/11springbyexample.org/examples/spring-modules-validation-module.html

ListFrom an array, L i s t , or S e t , a value from it can be returned byspecifying it's index. Only arrays and lists are supported bybytecode generation.

a d d r e s s e s [ 1 ] I SN O T N U L L

Map From a M a p , the value based on the key specified is retrieved.a d d r e s s e s [ h o m e ]I S N O T N U L L

Functions

These are built in functions that come with Valang. The function framework is pluggable, so it'seasy to add custom functions. Adding custom functions will be covered in the next section.

Table 6. Functions

Function Description Example

length |len | size| count

Returns the size of a collection or an array,and otherwise returns the length of string bycalled t o S t r i n g ( ) on the object.

l e n g t h ( f i r s t N a m e ) < 2 0

match |matches

Performs a match on a regular expression. Thefirst argument is the regular expression andthe second is the value match on.

m a t c h e s ( ' \ \ w + ' , f i r s t N a m e ) I ST R U E

email Checks if the value is a valid e-mail address. e m a i l ( e m a i l ) I S T R U E

upper Converts the value to uppercase. u p p e r ( f i r s t N a m e ) E Q U A L S ' J O E '

lower Converts the value to lowercase. l o w e r ( f i r s t N a m e ) E Q U A L S ' j o e '

resolveWraps a string inD e f a u l t M e s s a g e S o u r c e R e s o l v a b l e .

r e s o l v e ( ' p e r s o n F o r m . f i r s t N a m e ' )E Q U A L S ' F i r s t N a m e '

inRoleChecks if the user authenticated by SpringSecurity is in a role.

i n R o l e ( ' A D M I N ' ) I S T R U E

Custom Functions

Custom functions can either be explicitly registered or instances of F u n c t i o n D e f i n i t i o n andF u n c t i o n W r a p p e r are automatically registered with a V a l a n g V a l i d a t o r . If just specifying a classname, it must have a constructor with the signature F u n c t i o n [ ] a r g u m e n t s , i n t l i n e , i n t c o l u m n .The F u n c t i o n W r a p p e r is specifically for Spring configured functions. If the F u n c t i o n in aF u n c t i o n W r a p p e r takes any arguments, it must implement C o n f i g u r a b l e F u n c t i o n which allows theparser to configure the arguments, line number, and column number. Otherwise the line &column number will not be set on a Spring configured function.

Note

It's important for a F u n c t i o n W r a p p e r around a custom F u n c t i o n to be of thescope prototype as well as the F u n c t i o n W r a p p e r . Also the F u n c t i o n W r a p p e r musthave <aop:scoped-proxy/> defined so each call to it will get a new instanceof the function. This is because as the validation language is parsed a newinstance of a function is made each time and has the arguments specific tothat function set on it.

Spring Configuration

The example below shows how to explicitly register a custom function directly with a validator.The custom functions 'validLastName' and 'creditApproval' are registered on the c u s t o m F u n c t i o n s

property as a M a p . The key is the name of the function to be used in the validation language andthe value if the function being registered, which can either be the fully qualified name of theclass or an instance of F u n c t i o n W r a p p e r .

ValangValidatorCustomFunctionTest-context.xml

< ? x m l v e r s i o n = " 1 . 0 " e n c o d i n g = " U T F - 8 " ? >< b e a n s x m l n s = " h t t p : / / w w w . s p r i n g f r a m e w o r k . o r g / s c h e m a / b e a n s " x m l n s : x s i = " h t t p : / / w w w . w 3 . o r g / 2 0 0 1 / X M L S c h e m a - i n s t a n c e " x m l n s : a o p = " h t t p : / / w w w . s p r i n g f r a m e w o r k . o r g / s c h e m a / a o p " x s i : s c h e m a L o c a t i o n = " h t t p : / / w w w . s p r i n g f r a m e w o r k . o r g / s c h e m a / b e a n s h t t p : / / w w w . s p r i n g f r a m e w o r k . o r g / s c h e m a / b e a n s / s p r i n g - b e a n s . x s d

h t t p : / / w w w . s p r i n g f r a m e w o r k . o r g / s c h e m a / a o p

Page 7: Spring Modules Validation

12/14/11 Spring Modules Validation

7/11springbyexample.org/examples/spring-modules-validation-module.html

h t t p : / / w w w . s p r i n g f r a m e w o r k . o r g / s c h e m a / a o p h t t p : / / w w w . s p r i n g f r a m e w o r k . o r g / s c h e m a / a o p / s p r i n g - a o p . x s d " >

< b e a n i d = " c r e d i t A p p r o v a l F u n c t i o n " c l a s s = " o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . C r e d i t A p p r o v a l F u n c t i o n " s c o p e = " p r o t o t y p e " > < p r o p e r t y n a m e = " c r e d i t R a t i n g L i s t " > < l i s t > < v a l u e > G O O D < / v a l u e > < v a l u e > E X C E L L E N T < / v a l u e > < / l i s t > < / p r o p e r t y > < / b e a n >

< b e a n i d = " p e r s o n V a l i d a t o r " c l a s s = " o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . V a l a n g V a l i d a t o r " > < p r o p e r t y n a m e = " c l a s s N a m e " v a l u e = " o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . P e r s o n " / > < p r o p e r t y n a m e = " c u s t o m F u n c t i o n s " > < m a p > < e n t r y k e y = " v a l i d L a s t N a m e " > < v a l u e > o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . V a l i d L a s t N a m e F u n c t i o n < / v a l u e > < / e n t r y > < e n t r y k e y = " c r e d i t A p p r o v a l " > < b e a n c l a s s = " o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . f u n c t i o n s . F u n c t i o n W r a p p e r " s c o p e = " p r o t o t y p e " > < a o p : s c o p e d - p r o x y / > < p r o p e r t y n a m e = " f u n c t i o n " r e f = " c r e d i t A p p r o v a l F u n c t i o n " / > < / b e a n > < / e n t r y > < / m a p > < / p r o p e r t y > < ! - - F i n a l v a l i d a t i o n t e s t s t h a t t h e a o p : s c o p e d - p r o x y i s w o r k i n g s i n c e i f t h e s a m e i n s t a n c e o f C r e d i t A p p r o v a l F u n c t i o n i s u s e d i t w i l l b e s e t t o a f a i l i n g v a l u e f o r b o t h s i d e s o f t h e o r . W h i l e i f t w o i n s t a n c e s a r e m a d e t h e f i r s t c o n d i t i o n s h o u l d p a s s w h i l e t h e s e c o n d w i l l f a i l . - - > < p r o p e r t y n a m e = " v a l a n g " > < v a l u e > < ! [ C D A T A [ { l a s t N a m e : v a l i d L a s t N a m e ( ? ) i s t r u e : ' ' } { l a s t N a m e : c r e d i t A p p r o v a l ( a g e , c r e d i t R a t i n g ) i s t r u e : ' ' } { l a s t N a m e : v a l i d L a s t N a m e ( ? ) i s t r u e A N D c r e d i t A p p r o v a l ( a g e , c r e d i t R a t i n g ) i s t r u e : ' ' } { l a s t N a m e : v a l i d L a s t N a m e ( ? ) i s t r u e A N D ( c r e d i t A p p r o v a l ( a g e , c r e d i t R a t i n g ) i s t r u e O R c r e d i t A p p r o v a l ( a g e , [ ' o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . P e r s o n $ C r e d i t R a t i n g . F A I R ' ] ) i s t r u e ) : ' ' } ] ] < < / v a l u e > < / p r o p e r t y > < / b e a n > < / b e a n s >

Instances of F u n c t i o n D e f i n i t i o n and F u n c t i o n W r a p p e r are automatically registered with aV a l a n g V a l i d a t o r The custom functions 'validLastName' and 'creditApproval' are registered. If aF u n c t i o n W r a p p e r doesn't have a function name specified, the name of the bean will be used forthe function name.

ValangValidatorCustomFunctionDiscoveryTest-context.xml

< ? x m l v e r s i o n = " 1 . 0 " e n c o d i n g = " U T F - 8 " ? >< b e a n s x m l n s = " h t t p : / / w w w . s p r i n g f r a m e w o r k . o r g / s c h e m a / b e a n s " x m l n s : x s i = " h t t p : / / w w w . w 3 . o r g / 2 0 0 1 / X M L S c h e m a - i n s t a n c e " x m l n s : a o p = " h t t p : / / w w w . s p r i n g f r a m e w o r k . o r g / s c h e m a / a o p " x m l n s : p = " h t t p : / / w w w . s p r i n g f r a m e w o r k . o r g / s c h e m a / p " x s i : s c h e m a L o c a t i o n = " h t t p : / / w w w . s p r i n g f r a m e w o r k . o r g / s c h e m a / b e a n s h t t p : / / w w w . s p r i n g f r a m e w o r k . o r g / s c h e m a / b e a n s / s p r i n g - b e a n s . x s d h t t p : / / w w w . s p r i n g f r a m e w o r k . o r g / s c h e m a / a o p h t t p : / / w w w . s p r i n g f r a m e w o r k . o r g / s c h e m a / a o p / s p r i n g - a o p . x s d " >

< b e a n c l a s s = " o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . f u n c t i o n s . F u n c t i o n D e f i n i t i o n " p : n a m e = " v a l i d L a s t N a m e " p : c l a s s N a m e = " o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . V a l i d L a s t N a m e F u n c t i o n " / >

< ! - - U s e s b e a n n a m e f o r f u n c t i o n n a m e i f n o t e x p l i c i t l y s e t o n t h e w r a p p e r - - > < b e a n i d = " c r e d i t A p p r o v a l " c l a s s = " o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . f u n c t i o n s . F u n c t i o n W r a p p e r " s c o p e = " p r o t o t y p e " > < a o p : s c o p e d - p r o x y / > < p r o p e r t y n a m e = " f u n c t i o n " > < b e a n i d = " c r e d i t A p p r o v a l F u n c t i o n " c l a s s = " o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . C r e d i t A p p r o v a l F u n c t i o n " s c o p e = " p r o t o t y p e " > < p r o p e r t y n a m e = " c r e d i t R a t i n g L i s t " > < l i s t > < v a l u e > G O O D < / v a l u e > < v a l u e > E X C E L L E N T < / v a l u e > < / l i s t > < / p r o p e r t y > < / b e a n > < / p r o p e r t y > < / b e a n > < b e a n i d = " p e r s o n V a l i d a t o r " c l a s s = " o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . V a l a n g V a l i d a t o r " > < p r o p e r t y n a m e = " c l a s s N a m e " v a l u e = " o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . P e r s o n " / > < ! - - F i n a l v a l i d a t i o n t e s t s t h a t t h e a o p : s c o p e d - p r o x y i s w o r k i n g s i n c e i f t h e s a m e i n s t a n c e o f C r e d i t A p p r o v a l F u n c t i o n i s u s e d i t w i l l b e s e t t o a f a i l i n g v a l u e f o r b o t h s i d e s o f t h e o r . W h i l e i f t w o i n s t a n c e s a r e m a d e t h e f i r s t c o n d i t i o n s h o u l d p a s s w h i l e t h e s e c o n d w i l l f a i l . - - > < p r o p e r t y n a m e = " v a l a n g " > < v a l u e > < ! [ C D A T A [

{ l a s t N a m e : v a l i d L a s t N a m e ( ? ) i s t r u e : ' ' }

Page 8: Spring Modules Validation

12/14/11 Spring Modules Validation

8/11springbyexample.org/examples/spring-modules-validation-module.html

{ l a s t N a m e : v a l i d L a s t N a m e ( ? ) i s t r u e : ' ' } { l a s t N a m e : c r e d i t A p p r o v a l ( a g e , c r e d i t R a t i n g ) i s t r u e : ' ' } { l a s t N a m e : v a l i d L a s t N a m e ( ? ) i s t r u e A N D c r e d i t A p p r o v a l ( a g e , c r e d i t R a t i n g ) i s t r u e : ' ' } { l a s t N a m e : v a l i d L a s t N a m e ( ? ) i s t r u e A N D ( c r e d i t A p p r o v a l ( a g e , c r e d i t R a t i n g ) i s t r u e O R c r e d i t A p p r o v a l ( a g e , [ ' o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . P e r s o n $ C r e d i t R a t i n g . F A I R ' ] ) i s t r u e ) : ' ' } ] ] < < / v a l u e > < / p r o p e r t y > < / b e a n > < / b e a n s >

Code Example

Checks if the last name is in a list, and if it isn't f a l s e is returned.

Example 1. V a l i d L a s t N a m e F u n c t i o n

p u b l i c c l a s s V a l i d L a s t N a m e F u n c t i o n e x t e n d s A b s t r a c t F u n c t i o n {

f i n a l L o g g e r l o g g e r = L o g g e r F a c t o r y . g e t L o g g e r ( V a l i d L a s t N a m e F u n c t i o n . c l a s s ) ; f i n a l S e t < S t r i n g > l V a l i d L a s t N a m e s = n e w H a s h S e t < S t r i n g > ( ) ; / * * * C o n s t r u c t o r * / p u b l i c V a l i d L a s t N a m e F u n c t i o n ( F u n c t i o n [ ] a r g u m e n t s , i n t l i n e , i n t c o l u m n ) { s u p e r ( a r g u m e n t s , l i n e , c o l u m n ) ; d e f i n e d E x a c t N u m b e r O f A r g u m e n t s ( 1 ) ;

l V a l i d L a s t N a m e s . a d d ( " A n d e r s o n " ) ; l V a l i d L a s t N a m e s . a d d ( " J a c k s o n " ) ; l V a l i d L a s t N a m e s . a d d ( " J o h n s o n " ) ; l V a l i d L a s t N a m e s . a d d ( " J o n e s " ) ; l V a l i d L a s t N a m e s . a d d ( " S m i t h " ) ; }

/ * * * C h e c k s i f t h e l a s t n a m e i s b l o c k e d . * * @ r e t u r n O b j e c t R e t u r n s a < c o d e > b o o l e a n < / c o d e > f o r * w h e t h e r o r n o t t h e l a s t n a m e i s b l o c k e d . * / @ O v e r r i d e p r o t e c t e d O b j e c t d o G e t R e s u l t ( O b j e c t t a r g e t ) { b o o l e a n r e s u l t = t r u e ; S t r i n g s y m b o l = g e t A r g u m e n t s ( ) [ 0 ] . g e t R e s u l t ( t a r g e t ) . t o S t r i n g ( ) ; i f ( ! l V a l i d L a s t N a m e s . c o n t a i n s ( s y m b o l ) ) { r e s u l t = f a l s e ; } r e t u r n r e s u l t ; } }

The function checks if a person can get credit approval. Their credit rating is checked against alist only if they are over 18 years old.

Example 2. C o n f i g u r a b l e F u n c t i o n

p u b l i c c l a s s C r e d i t A p p r o v a l F u n c t i o n e x t e n d s A b s t r a c t F u n c t i o n i m p l e m e n t s C o n f i g u r a b l e F u n c t i o n {

f i n a l L o g g e r l o g g e r = L o g g e r F a c t o r y . g e t L o g g e r ( C r e d i t A p p r o v a l F u n c t i o n . c l a s s ) ; S e t < P e r s o n . C r e d i t R a t i n g > l C r e d i t R a t i n g s = n e w H a s h S e t < P e r s o n . C r e d i t R a t i n g > ( ) ;

/ * * * C o n s t r u c t o r * / p u b l i c C r e d i t A p p r o v a l F u n c t i o n ( ) { }

/ * * * C o n s t r u c t o r * / p u b l i c C r e d i t A p p r o v a l F u n c t i o n ( F u n c t i o n [ ] a r g u m e n t s , i n t l i n e , i n t c o l u m n ) { s u p e r ( a r g u m e n t s , l i n e , c o l u m n ) ; d e f i n e d E x a c t N u m b e r O f A r g u m e n t s ( 2 ) ; l C r e d i t R a t i n g s . a d d ( P e r s o n . C r e d i t R a t i n g . F A I R ) ; l C r e d i t R a t i n g s . a d d ( P e r s o n . C r e d i t R a t i n g . G O O D ) ; l C r e d i t R a t i n g s . a d d ( P e r s o n . C r e d i t R a t i n g . E X C E L L E N T ) ; }

Page 9: Spring Modules Validation

12/14/11 Spring Modules Validation

9/11springbyexample.org/examples/spring-modules-validation-module.html

/ * * * G e t s n u m b e r o f e x p e c t e d a r g u m e n t s . * I m p l e m e n t a t i o n o f < c o d e > C o n f i g u r a b l e F u n c t i o n < / c o d e > . * / p u b l i c i n t g e t E x p e c t e d N u m b e r O f A r g u m e n t s ( ) { r e t u r n 2 ; }

/ * * * S e t s a r g u m e n t s , l i n e n u m b e r , a n d c o l u m n n u m b e r . * I m p l e m e n t a t i o n o f < c o d e > C o n f i g u r a b l e F u n c t i o n < / c o d e > . * / p u b l i c v o i d s e t A r g u m e n t s ( i n t e x p e c t e d N u m b e r O f A r g u m e n t s , F u n c t i o n [ ] a r g u m e n t s , i n t l i n e , i n t c o l u m n ) { / / i m p o r t a n t t o s e t t e m p l a t e f i r s t o r c a n c a u s e a N u l l P o i n t e r E x c e p t i o n / / i f n u m b e r o f a r g u m e n t s d o n ' t m a t c h t h e e x p e c t e d n u m b e r s i n c e / / t h e t e m p l a t e i s u s e d t o c r e a t e t h e e x c e p t i o n s u p e r . s e t T e m p l a t e ( l i n e , c o l u m n ) ; s u p e r . s e t A r g u m e n t s ( a r g u m e n t s ) ; s u p e r . d e f i n e d E x a c t N u m b e r O f A r g u m e n t s ( e x p e c t e d N u m b e r O f A r g u m e n t s ) ; } / * * * S e t s v a l i d c r e d i t r a t i n g a p p r o v a l l i s t . * / p u b l i c v o i d s e t C r e d i t R a t i n g L i s t ( S e t < P e r s o n . C r e d i t R a t i n g > l C r e d i t R a t i n g s ) { t h i s . l C r e d i t R a t i n g s = l C r e d i t R a t i n g s ; }

/ * * * I f a g e i s o v e r 1 8 , c h e c k i f t h e p e r s o n h a s g o o d c r e d i t , * a n d o t h e r w i s e r e j e c t . * * @ r e t u r n O b j e c t R e t u r n s a < c o d e > b o o l e a n < / c o d e > f o r * w h e t h e r o r n o t t h e p e r s o n h a s g o o d e n o u g h * c r e d i t t o g e t a p p r o v a l . * / @ O v e r r i d e p r o t e c t e d O b j e c t d o G e t R e s u l t ( O b j e c t t a r g e t ) { b o o l e a n r e s u l t = t r u e ; i n t a g e = ( I n t e g e r ) g e t A r g u m e n t s ( ) [ 0 ] . g e t R e s u l t ( t a r g e t ) ; P e r s o n . C r e d i t R a t i n g c r e d i t R a t i n g = ( P e r s o n . C r e d i t R a t i n g ) g e t A r g u m e n t s ( ) [ 1 ] . g e t R e s u l t ( t a r g e t ) ;

/ / m u s t b e o v e r 1 8 t o g e t c r e d i t a p p r o v a l i f ( a g e > 1 8 ) { i f ( ! l C r e d i t R a t i n g s . c o n t a i n s ( c r e d i t R a t i n g ) ) { r e s u l t = f a l s e ; } } r e t u r n r e s u l t ; } }

Bytecode Generation

If the validator will only be used to validate a specific class, the property 'className' can bespecified to avoid reflection. If it's set, a custom F u n c t i o n will be generated that directlyretrieves a property to avoid reflection. This provides a significant performance improvement ifthat is a concern, which typically isn't if the validation is being used to validate a web pagesince the delay is so small either way.

Note

Only a M a p , a L i s t , or an Array is supported by bytecode generation, not a S e t .Primitive arrays currently aren't supported, but any object one is. Also, nestedproperties are currently not supported.

This is a small excerpt from the logging of the performance unit test. As you can see from thelogging, as the validator is initialized it generates bytecode and shows for which class andmethod, as well as what the generated class name is. The package and name of the originalclass is used and then has what property is being retrieved appended along with'BeanPropertyFunction$$Valang' to make a unique class name to try to avoid any collisions.

D e f a u l t V i s i t o r - G e n e r a t e d b y t e c o d e f o r o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . P e r s o n . g e t L a s t N a m e ( ) a s ' o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . P e r s o n L a s t N a m e B e a n P r o p e r t y F u n c t i o n $ $ V a l a n g ' .D e f a u l t V i s i t o r - G e n e r a t e d b y t e c o d e f o r o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . P e r s o n . g e t A g e ( ) a s ' o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . P e r s o n A g e B e a n P r o p e r t y F u n c t i o n $ $ V a l a n g ' .D e f a u l t V i s i t o r - G e n e r a t e d b y t e c o d e f o r o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . P e r s o n . g e t C r e d i t R a t i n g ( ) a s ' o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . P e r s o n C r e d i t R a t i n g B e a n P r o p e r t y F u n c t i o n $ $ V a l a n g ' .D e f a u l t V i s i t o r - G e n e r a t e d b y t e c o d e f o r o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . P e r s o n . g e t F i r s t N a m e ( ) a s ' o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . P e r s o n F i r s t N a m e B e a n P r o p e r t y F u n c t i o n $ $ V a l a n g ' .D e f a u l t V i s i t o r - G e n e r a t e d b y t e c o d e f o r o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . P e r s o n . g e t C r e d i t S t a t u s ( )

a s ' o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . P e r s o n C r e d i t S t a t u s B e a n P r o p e r t y F u n c t i o n $ $ V a l a n g ' .

Page 10: Spring Modules Validation

12/14/11 Spring Modules Validation

10/11springbyexample.org/examples/spring-modules-validation-module.html

a s ' o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . P e r s o n C r e d i t S t a t u s B e a n P r o p e r t y F u n c t i o n $ $ V a l a n g ' .V a l a n g V a l i d a t o r P e r f o r m a n c e T e s t - T o o k 7 0 9 8 . 0 n s .V a l a n g V a l i d a t o r P e r f o r m a n c e T e s t - T o o k 2 1 2 4 . 0 n s .V a l a n g V a l i d a t o r P e r f o r m a n c e T e s t - M e s s a g e v a l i d a t o r t o o k 7 0 9 8 . 0 n s , a n d b y t e c o d e m e s s a g e v a l d i a t o r t o o k 2 1 2 4 . 0 n s .

Results from V a l a n g V a l i d a t o r P e r f o r m a n c e T e s t which was run on a Macbook Pro (2.5GHz Intel DualCore 2 Duo with 4 GB RAM with OS X 10.5.6) with Java 5. All the expressions are identical, butadjusted to either retrieve the values being compared from a JavaBean, M a p , L i s t , or an array.

Table 7. Bytecode Generation Performance Comparison

Expression ReflectionBytcode

Generation

{ lastName : validLastName(?) is true AND creditApproval(age,creditRating) is true WHERE firstName IN 'Joe', 'Jack', 'Jill', 'Jane' ANDcreditStatus IN['org.springmodules.validation.valang.CreditStatus.PENDING'],['org.springmodules.validation.valang.CreditStatus.FAIL'] ANDcreditRating EQUALS['org.springmodules.validation.valang.Person$CreditRating.EXCELLENT']AND age > 18 : '' }

7098ns 2124ns

{ mapVars[lastName] : validLastName(?) is true ANDcreditApproval(mapVars[age], mapVars[creditRating]) is true WHEREmapVars[firstName] IN 'Joe', 'Jack', 'Jill', 'Jane' ANDmapVars[creditStatus] IN['org.springmodules.validation.valang.CreditStatus.PENDING'],['org.springmodules.validation.valang.CreditStatus.FAIL'] ANDmapVars[creditRating] EQUALS['org.springmodules.validation.valang.Person$CreditRating.EXCELLENT']AND mapVars[age] > 18 : '' }

4902ns 237ns

{ listVars[1] : validLastName(?) is true AND creditApproval(listVars[2],listVars[4]) is true WHERE listVars[0] IN 'Joe', 'Jack', 'Jill', 'Jane' ANDlistVars[3] IN['org.springmodules.validation.valang.CreditStatus.PENDING'],['org.springmodules.validation.valang.CreditStatus.FAIL'] ANDlistVars[4] EQUALS['org.springmodules.validation.valang.Person$CreditRating.EXCELLENT']AND listVars[2] > 18 : '' }

2704ns 226ns

{ vars[1] : validLastName(?) is true AND creditApproval(vars[2],vars[4]) is true WHERE vars[0] IN 'Joe', 'Jack', 'Jill', 'Jane' AND vars[3]IN ['org.springmodules.validation.valang.CreditStatus.PENDING'],['org.springmodules.validation.valang.CreditStatus.FAIL'] AND vars[4]EQUALS['org.springmodules.validation.valang.Person$CreditRating.EXCELLENT']AND vars[2] > 18 : '' }

2918ns 212ns

Spring Configuration

By specifying the 'className' property, bytecode will be generated for each method being calledto avoid reflection. This gives a significant performance improvement.

Excerpt from ValangValidatorCustomFunctionTest-context.xml

< ! - - O n l y p e r f o r m v a l i d a t i o n i f v a l i d f i r s t n a m e , c r e d i t s t a t u s i s f a i l e d o r p e n d i n g , a n d t h e c r e d i t r a t i n g i s e x c e l l e n t w h e r e t h e p e r s o n ' s a g e i s o v e r 1 8 .- - >< b e a n i d = " e x p r e s s i o n " c l a s s = " j a v a . l a n g . S t r i n g " > < c o n s t r u c t o r - a r g > < v a l u e > < ! [ C D A T A [ { l a s t N a m e : v a l i d L a s t N a m e ( ? ) i s t r u e A N D c r e d i t A p p r o v a l ( a g e , c r e d i t R a t i n g ) i s t r u e W H E R E f i r s t N a m e I N ' J o e ' , ' J a c k ' , ' J i l l ' , ' J a n e ' A N D c r e d i t S t a t u s I N [ ' o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . C r e d i t S t a t u s . P E N D I N G ' ] , [ ' o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . C r e d i t S t a t u s . F A I L ' ] A N D c r e d i t R a t i n g E Q U A L S [ ' o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . P e r s o n $ C r e d i t R a t i n g . E X C E L L E N T ' ] A N D a g e > 1 8 : ' ' } ] ] < < / v a l u e > < / c o n s t r u c t o r - a r g >< / b e a n >

. . .

Page 11: Spring Modules Validation

12/14/11 Spring Modules Validation

11/11springbyexample.org/examples/spring-modules-validation-module.html

< b e a n i d = " b y t e c o d e P e r s o n V a l i d a t o r " c l a s s = " o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . V a l a n g V a l i d a t o r " > < p r o p e r t y n a m e = " c l a s s N a m e " v a l u e = " o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . P e r s o n " / > < p r o p e r t y n a m e = " v a l a n g " r e f = " e x p r e s s i o n " / >< / b e a n >

Date Examples

The default date parser provides support for a number of different date literals, and also hassupport for shifting and manipulating dates. Below are a few examples, but see theD e f a u l t D a t e P a r s e r for more detailed information.

Spring Configuration

ValangValidatorDateTest-context.xml

< ? x m l v e r s i o n = " 1 . 0 " e n c o d i n g = " U T F - 8 " ? >< b e a n s x m l n s = " h t t p : / / w w w . s p r i n g f r a m e w o r k . o r g / s c h e m a / b e a n s " x m l n s : x s i = " h t t p : / / w w w . w 3 . o r g / 2 0 0 1 / X M L S c h e m a - i n s t a n c e " x m l n s : a o p = " h t t p : / / w w w . s p r i n g f r a m e w o r k . o r g / s c h e m a / a o p " x s i : s c h e m a L o c a t i o n = " h t t p : / / w w w . s p r i n g f r a m e w o r k . o r g / s c h e m a / b e a n s h t t p : / / w w w . s p r i n g f r a m e w o r k . o r g / s c h e m a / b e a n s / s p r i n g - b e a n s . x s d h t t p : / / w w w . s p r i n g f r a m e w o r k . o r g / s c h e m a / a o p h t t p : / / w w w . s p r i n g f r a m e w o r k . o r g / s c h e m a / a o p / s p r i n g - a o p . x s d " >

< b e a n i d = " p e r s o n V a l i d a t o r " c l a s s = " o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . V a l a n g V a l i d a t o r " > < p r o p e r t y n a m e = " c l a s s N a m e " v a l u e = " o r g . s p r i n g m o d u l e s . v a l i d a t i o n . v a l a n g . P e r s o n " / > < p r o p e r t y n a m e = " v a l a n g " > < ! - - T h i r d t o l a s t v a l i d a t i o n s h i f t s ' 2 0 0 8 - 1 2 - 3 0 < y ' t o ' 2 0 0 8 - 0 1 - 0 1 0 0 : 0 0 : 0 0 ' S e c o n d t o l a s t v a l i d a t i o n s h i f t s ' 2 0 0 5 - 0 4 - 0 9 2 3 : 3 0 : 0 0 < M + 1 0 d + 8 H ' t o ' 2 0 0 5 - 0 4 - 1 1 0 8 : 0 0 : 0 0 ' . L a s t s h i f t s ' 2 0 0 9 - 0 2 - 0 6 0 0 : 0 0 : 0 0 < M + 2 0 y ' t o ' 2 0 2 9 - 0 2 - 0 1 0 0 : 0 0 : 0 0 ' . - - > < v a l u e > < ! [ C D A T A [ { l a s t U p d a t e d : ? > [ 2 0 0 8 1 2 3 0 ] : ' ' } { l a s t U p d a t e d : ? > [ 2 0 0 8 - 1 2 - 3 0 ] : ' ' } { l a s t U p d a t e d : ? > [ 2 0 0 8 - 1 2 - 3 0 1 2 : 2 0 : 3 1 ] : ' ' } { l a s t U p d a t e d : ? > [ 2 0 0 8 1 2 3 0 1 2 2 0 3 1 ] : ' ' } { l a s t U p d a t e d : ? > [ 2 0 0 8 1 2 3 0 1 2 : 2 0 : 3 1 ] : ' ' } { l a s t U p d a t e d : ? > [ 2 0 0 8 - 1 2 - 3 0 1 2 2 0 3 1 ] : ' ' } { l a s t U p d a t e d : ? B E T W E E N [ 2 0 0 8 1 2 3 0 ] A N D [ 2 0 0 9 - 0 2 - 0 6 0 0 : 0 0 : 0 0 < M + 2 0 y ] : ' ' } { l a s t U p d a t e d : ? > [ 2 0 0 8 - 1 2 - 3 0 < y ] : ' ' } { l a s t U p d a t e d : ? > [ 2 0 0 5 - 0 4 - 0 9 2 3 : 3 0 : 0 0 < M + 1 0 d + 8 H ] : ' ' } { l a s t U p d a t e d : ? < [ 2 0 0 9 - 0 2 - 0 6 0 0 : 0 0 : 0 0 < M + 2 0 y ] : ' ' } ] ] < < / v a l u e > < / p r o p e r t y > < / b e a n > < / b e a n s >

© 2009 David Winterfeldt. All rights reserved.

Prev

Up

Next

5. Reference Home

2. Download