In the Coding Actions lesson, we validated the username and password input with a few lines of Java code. Of course, in a larger application, over time, even these few lines of code can become a maintenance burden.

Happily, the framework provides a validation framework that can validate input "behind the scenes".

The Code

Validation can be described through an XML document, or using annotations. The XML document is named after the Action being validated with a "-validation" suffix. Since we would like to validate the Logon Action class, our document is named Logon-validation.xml.

Logon-validation.xml
<!DOCTYPE validators PUBLIC 
"-//OpenSymphony Group//XWork Validator 1.0.2//EN" 
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">

<validators>
    <field name="username">
        <field-validator type="requiredstring">
            <message>Username is required</message>
        </field-validator>
    </field>
    <field name="password">
        <field-validator type="requiredstring">
            <message>Password is required</message>
        </field-validator>
    </field>
</validators>

Create a file named Logon-validation.xml next to the Logon.java class, and paste in the code.

The first time a page displays, we wouldn't want the validation to fire. We should have a chance to enter the input before being told it's incorrect. One way to bypass validation is to refer to a special "input" method provided by the base ActionSupport class. To do that, we need to edit the Welcome page and the Logon mapping.

To indicate the changes, we'll use (minus) to indicate a line we are removing, and (plus) to indicated a line we are adding.

Welcome.jsp

(minus) <li><a href="<s:url action="Logon"/>">Sign On</a></li>
(plus) <li><a href="<s:url action="Logon_input"/>">Sign On</a></li>

struts.xml

(minus) <action name="Logon" class="tutorial.Logon">
(plus) <action name="Logon_*" method="{1}" class="tutorial.Logon">

How the Code Works

To open the Logon form, the Welcome page refers to Logon_input.

  • The framework matches this reference with the Logon_* action mapping.
  • The "method={1}" attribute is replaced with "method=input".
  • The framework invokes the input method on the Logon Action class.
  • Since "input" is on a special list of methods that bypass validation, the validation framework is not invoked.
  • The default input method returns the result code "input".
  • The framework renders "Logon.jsp" as the response, without any validation messages.

To submit the Logon form, the Login pages refers to Logon.

  • The framework checks for a validation for the target Action class, Logon.
  • Finding a Logon-validation.xml file, the framework creates a validation object for the class, based on the XML document.
    • Essentially, the validation is a set of Validator objects.
  • The Validators are applied to the incoming properties.
  • If a Validator fails, its message is added to an internal queue.
  • When all the Validators have fired, if the framework sees that errors have been posted, it seeks the "input" result, without invoking the Action class.
  • Otherwise, the default Action method fires. Since the input has already been validated, the "success" result code is returned.

What to Remember

The framework provides a validation framework. A set of validators can be associated with an input field. If validation fails, the framework can return to the input page and display the error messages. To bypass validation, a special "input" Action method can be invoked, instead of the default "execute" method.

(lightbulb) For more, see Validation in the Core Developers Guide.

  • No labels

4 Comments

  1. Correction to comment posted by Vivek Chauhan

    Move the following piece of code
    <action name="*">
    <result>/tutorial/{1}.jsp</result>
    </action>
    to the bottom of struts.xml, otherwise Struts will try to find Logon_input.jsp as instructed by entry

  2. Anonymous

    if the mapping is changed to <action name="Logon_*" method="

    Unknown macro: {1}

    " class="tutorial.Logon">, why is "http://localhost:8080/tutorial/Logon" still mapped to "tutorial.Logon", even though the URL doesn't have an underscore "_" after "Logon"?

    1. Aren't you talking about the class attribute?

      1. Anonymous

        My question is if

        <action name="Logon_*" method="{1}" class="tutorial.Logon">
        

        has an underscore in "Logon_", why is "http://localhost:8080/tutorial/Logon" still mapped to "tutorial.Logon", even though "Logon" in this URL does not have an under score?

        thanks!