| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"/> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"/> |
| <meta name="Date-Revision-yyyymmdd" content="20140918"/> |
| <meta http-equiv="Content-Language" content="en"/> |
| <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> |
| |
| <title>Validation</title> |
| |
| <link href="//fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,400italic,600italic,700italic" rel="stylesheet" type="text/css"> |
| <link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet"> |
| <link href="/css/main.css" rel="stylesheet"> |
| <link href="/css/custom.css" rel="stylesheet"> |
| <link href="/css/syntax.css" rel="stylesheet"> |
| |
| <script src="//code.jquery.com/jquery-1.11.0.min.js"></script> |
| <script type="text/javascript" src="/bootstrap/js/bootstrap.js"></script> |
| <script type="text/javascript" src="/js/community.js"></script> |
| |
| <!-- Matomo --> |
| <script> |
| var _paq = window._paq = window._paq || []; |
| /* tracker methods like "setCustomDimension" should be called before "trackPageView" */ |
| /* We explicitly disable cookie tracking to avoid privacy issues */ |
| _paq.push(['disableCookies']); |
| _paq.push(['trackPageView']); |
| _paq.push(['enableLinkTracking']); |
| (function() { |
| var u="//analytics.apache.org/"; |
| _paq.push(['setTrackerUrl', u+'matomo.php']); |
| _paq.push(['setSiteId', '41']); |
| var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; |
| g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s); |
| })(); |
| </script> |
| <!-- End Matomo Code --> |
| </head> |
| <body> |
| |
| <a href="https://github.com/apache/struts" class="github-ribbon"> |
| <img decoding="async" loading="lazy" style="position: absolute; right: 0; border: 0;" width="149" height="149" src="https://github.blog/wp-content/uploads/2008/12/forkme_right_red_aa0000.png?resize=149%2C149" class="attachment-full size-full" alt="Fork me on GitHub" data-recalc-dims="1"> |
| </a> |
| |
| <header> |
| <nav> |
| <div role="navigation" class="navbar navbar-default navbar-fixed-top"> |
| <div class="container"> |
| <div class="navbar-header"> |
| <button type="button" data-toggle="collapse" data-target="#struts-menu" class="navbar-toggle"> |
| Menu |
| <span class="sr-only">Toggle navigation</span> |
| <span class="icon-bar"></span> |
| <span class="icon-bar"></span> |
| <span class="icon-bar"></span> |
| </button> |
| <a href="/index.html" class="navbar-brand logo"><img src="/img/struts-logo.svg"></a> |
| </div> |
| <div id="struts-menu" class="navbar-collapse collapse"> |
| <ul class="nav navbar-nav"> |
| <li class="dropdown"> |
| <a data-toggle="dropdown" href="#" class="dropdown-toggle"> |
| Home<b class="caret"></b> |
| </a> |
| <ul class="dropdown-menu"> |
| <li><a href="/index.html">Welcome</a></li> |
| <li><a href="/download.cgi">Download</a></li> |
| <li><a href="/releases.html">Releases</a></li> |
| <li><a href="/announce-2023.html">Announcements</a></li> |
| <li><a href="http://www.apache.org/licenses/">License</a></li> |
| <li><a href="https://www.apache.org/foundation/thanks.html">Thanks!</a></li> |
| <li><a href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li> |
| <li><a href="https://privacy.apache.org/policies/privacy-policy-public.html">Privacy Policy</a></li> |
| </ul> |
| </li> |
| <li class="dropdown"> |
| <a data-toggle="dropdown" href="#" class="dropdown-toggle"> |
| Support<b class="caret"></b> |
| </a> |
| <ul class="dropdown-menu"> |
| <li><a href="/mail.html">User Mailing List</a></li> |
| <li><a href="https://issues.apache.org/jira/browse/WW">Issue Tracker</a></li> |
| <li><a href="/security.html">Reporting Security Issues</a></li> |
| <li><a href="/commercial-support.html">Commercial Support</a></li> |
| <li class="divider"></li> |
| <li><a href="https://cwiki.apache.org/confluence/display/WW/Migration+Guide">Version Notes</a></li> |
| <li><a href="https://cwiki.apache.org/confluence/display/WW/Security+Bulletins">Security Bulletins</a></li> |
| <li class="divider"></li> |
| <li><a href="/maven/project-info.html">Maven Project Info</a></li> |
| <li><a href="/maven/struts2-core/dependencies.html">Struts Core Dependencies</a></li> |
| <li><a href="/maven/struts2-plugins/modules.html">Plugin Dependencies</a></li> |
| </ul> |
| </li> |
| <li class="dropdown"> |
| <a data-toggle="dropdown" href="#" class="dropdown-toggle"> |
| Documentation<b class="caret"></b> |
| </a> |
| <ul class="dropdown-menu"> |
| <li><a href="/birdseye.html">Birds Eye</a></li> |
| <li><a href="/primer.html">Key Technologies</a></li> |
| <li><a href="/kickstart.html">Kickstart FAQ</a></li> |
| <li><a href="https://cwiki.apache.org/confluence/display/WW/Home">Wiki</a></li> |
| <li class="divider"></li> |
| <li><a href="/getting-started/">Getting Started</a></li> |
| <li><a href="/security/">Security Guide</a></li> |
| <li><a href="/core-developers/">Core Developers Guide</a></li> |
| <li><a href="/tag-developers/">Tag Developers Guide</a></li> |
| <li><a href="/maven-archetypes/">Maven Archetypes</a></li> |
| <li><a href="/plugins/">Plugins</a></li> |
| <li><a href="/maven/struts2-core/apidocs/index.html">Struts Core API</a></li> |
| <li><a href="/tag-developers/tag-reference.html">Tag reference</a></li> |
| <li><a href="https://cwiki.apache.org/confluence/display/WW/FAQs">FAQs</a></li> |
| <li><a href="http://cwiki.apache.org/S2PLUGINS/home.html">Plugin registry</a></li> |
| </ul> |
| </li> |
| <li class="dropdown"> |
| <a data-toggle="dropdown" href="#" class="dropdown-toggle"> |
| Contributing<b class="caret"></b> |
| </a> |
| <ul class="dropdown-menu"> |
| <li><a href="/youatstruts.html">You at Struts</a></li> |
| <li><a href="/helping.html">How to Help FAQ</a></li> |
| <li><a href="/dev-mail.html">Development Lists</a></li> |
| <li class="divider"></li> |
| <li><a href="/submitting-patches.html">Submitting patches</a></li> |
| <li><a href="/builds.html">Source Code and Builds</a></li> |
| <li><a href="/coding-standards.html">Coding standards</a></li> |
| <li><a href="/contributors/">Contributors Guide</a></li> |
| <li class="divider"></li> |
| <li><a href="/release-guidelines.html">Release Guidelines</a></li> |
| <li><a href="/bylaws.html">PMC Charter</a></li> |
| <li><a href="/volunteers.html">Volunteers</a></li> |
| <li><a href="https://gitbox.apache.org/repos/asf?p=struts.git">Source Repository</a></li> |
| <li><a href="/updating-website.html">Updating the website</a></li> |
| </ul> |
| </li> |
| <li class="apache"><a href="http://www.apache.org/"><img src="/img/apache.png"></a></li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| </nav> |
| </header> |
| |
| |
| <article class="container"> |
| <section class="col-md-12"> |
| <a class="edit-on-gh" href="https://github.com/apache/struts-site/edit/master/source/core-developers/validation.md" title="Edit this page on GitHub">Edit on GitHub</a> |
| |
| <a href="index.html" title="back to Core Developers Guide"><< back to Core Developers Guide</a> |
| |
| <h1 class="no_toc" id="validation">Validation</h1> |
| |
| <ul id="markdown-toc"> |
| <li><a href="#using-annotations" id="markdown-toc-using-annotations">Using Annotations</a></li> |
| <li><a href="#bean-validation" id="markdown-toc-bean-validation">Bean Validation</a></li> |
| <li><a href="#examples" id="markdown-toc-examples">Examples</a></li> |
| <li><a href="#bundled-validators" id="markdown-toc-bundled-validators">Bundled Validators</a></li> |
| <li><a href="#registering-validators" id="markdown-toc-registering-validators">Registering Validators</a></li> |
| <li><a href="#turning-on-validation" id="markdown-toc-turning-on-validation">Turning on Validation</a></li> |
| <li><a href="#validator-scopes" id="markdown-toc-validator-scopes">Validator Scopes</a></li> |
| <li><a href="#notes" id="markdown-toc-notes">Notes</a></li> |
| <li><a href="#defining-validation-rules" id="markdown-toc-defining-validation-rules">Defining Validation Rules</a></li> |
| <li><a href="#localizing-and-parameterizing-messages" id="markdown-toc-localizing-and-parameterizing-messages">Localizing and Parameterizing Messages</a> <ul> |
| <li><a href="#customizing-validation-messages" id="markdown-toc-customizing-validation-messages">Customizing validation messages</a></li> |
| </ul> |
| </li> |
| <li><a href="#validator-flavor" id="markdown-toc-validator-flavor">Validator Flavor</a></li> |
| <li><a href="#non-field-validator-vs-field-validator-validatortypes" id="markdown-toc-non-field-validator-vs-field-validator-validatortypes">Non-Field Validator Vs Field-Validator validatortypes</a></li> |
| <li><a href="#short-circuiting-validator" id="markdown-toc-short-circuiting-validator">Short-Circuiting Validator</a></li> |
| <li><a href="#how-validators-of-an-action-are-found" id="markdown-toc-how-validators-of-an-action-are-found">How Validators of an Action are Found</a></li> |
| <li><a href="#writing-custom-validators" id="markdown-toc-writing-custom-validators">Writing custom validators</a></li> |
| <li><a href="#resources" id="markdown-toc-resources">Resources</a></li> |
| </ul> |
| |
| <p>Struts 2 validation is configured via XML or annotations. Manual validation in the action is also possible, and may be |
| combined with XML and annotation-driven validation.</p> |
| |
| <p>Validation also depends on both the <code class="language-plaintext highlighter-rouge">validation</code> and <code class="language-plaintext highlighter-rouge">workflow</code> interceptors (both are included in the default interceptor |
| stack). The <code class="language-plaintext highlighter-rouge">validation</code> interceptor does the validation itself and creates a list of field-specific errors. |
| The <code class="language-plaintext highlighter-rouge">workflow</code> interceptor checks for the presence of validation errors: if any are found, it returns the “input” result |
| (by default), taking the user back to the form which contained the validation errors.</p> |
| |
| <p>If we’re using the default settings <em>and</em> our action does not have an “input” result defined <em>and</em> there are validation |
| (or, incidentally, type conversion) errors, we’ll get an error message back telling us there’s no “input” result defined |
| for the action.</p> |
| |
| <h2 id="using-annotations">Using Annotations</h2> |
| |
| <p><a href="validation-annotation">Annotations</a> can be used as an alternative to XML for validation.</p> |
| |
| <h2 id="bean-validation">Bean Validation</h2> |
| |
| <p>With struts 2.5 comes the Bean Validation Plugin. That is an alternative to the classic struts validation described here. |
| See the <a href="../plugins/">Plugin Page</a> for details.</p> |
| |
| <h2 id="examples">Examples</h2> |
| |
| <p>In all examples given here, the validation message displayed is given in plain English - to internationalize the message, |
| put the string in a properties file and use a property key instead, specified by the ‘key’ attribute. It will be looked |
| up by the framework (see <a href="localization">Localization</a>).</p> |
| |
| <ol> |
| <li><a href="basic-validation">Basic Validation</a></li> |
| <li><a href="client-side-validation">Client-side Validation</a></li> |
| <li><em>AJAX Validation</em></li> |
| <li><a href="using-field-validators">Using Field Validators</a></li> |
| <li><a href="using-non-field-validators">Using Non Field Validators</a></li> |
| <li><a href="using-visitor-field-validator">Using Visitor Field Validator</a></li> |
| <li><em>How do we repopulate controls when validation fails</em> (FAQ entry)</li> |
| </ol> |
| |
| <h2 id="bundled-validators">Bundled Validators</h2> |
| |
| <p>When using a Field Validator, Field Validator Syntax is <strong>ALWAYS</strong> preferable than using the Plain Validator Syntax |
| as it facilitates grouping of field-validators according to fields. This is very handy especially if a field needs |
| to have many field-validators which is almost always the case.</p> |
| |
| <ol> |
| <li><a href="conversion-validator">conversion validator</a></li> |
| <li><a href="date-validator">date validator</a></li> |
| <li><a href="double-validator">double validator</a></li> |
| <li><a href="email-validator">email validator</a></li> |
| <li><a href="expression-validator">expression validator</a></li> |
| <li><a href="fieldexpression-validator">fieldexpression validator</a></li> |
| <li><a href="int-validator">int validator</a></li> |
| <li><a href="regex-validator">regex validator</a></li> |
| <li><a href="required-validator">required validator</a></li> |
| <li><a href="requiredstring-validator">requiredstring validator</a></li> |
| <li><a href="short-validator">short validator</a></li> |
| <li><a href="stringlength-validator">stringlength validator</a></li> |
| <li><a href="url-validator">url validator</a></li> |
| <li><a href="visitor-validator">visitor validator</a></li> |
| <li><a href="conditionalvisitor-validator">conditionalvisitor validator</a></li> |
| </ol> |
| |
| <h2 id="registering-validators">Registering Validators</h2> |
| |
| <p>Validation rules are handled by validators, which must be registered with the ValidatorFactory (using the |
| <code class="language-plaintext highlighter-rouge">registerValidator</code> method). The simplest way to do so is to add a file name <code class="language-plaintext highlighter-rouge">validators.xml</code> in the root of the classpath |
| (/WEB-INF/classes) that declares all the validators you intend to use.</p> |
| |
| <p>The following list shows the default validators included in the framework and is an example of the syntax used to declare |
| our own validators.</p> |
| |
| <figure class="highlight"><pre><code class="language-xml" data-lang="xml"><span class="cp"><?xml version="1.0" encoding="UTF-8"?></span> |
| <span class="c"><!-- |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| --></span> |
| <span class="cp"><!DOCTYPE validators PUBLIC |
| "-//Apache Struts//XWork Validator Definition 1.0//EN" |
| "https://struts.apache.org/dtds/xwork-validator-definition-1.0.dtd"></span> |
| |
| <span class="c"><!-- START SNIPPET: validators-default --></span> |
| <span class="nt"><validators></span> |
| <span class="nt"><validator</span> <span class="na">name=</span><span class="s">"required"</span> <span class="na">class=</span><span class="s">"com.opensymphony.xwork2.validator.validators.RequiredFieldValidator"</span><span class="nt">/></span> |
| <span class="nt"><validator</span> <span class="na">name=</span><span class="s">"requiredstring"</span> <span class="na">class=</span><span class="s">"com.opensymphony.xwork2.validator.validators.RequiredStringValidator"</span><span class="nt">/></span> |
| <span class="nt"><validator</span> <span class="na">name=</span><span class="s">"int"</span> <span class="na">class=</span><span class="s">"com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator"</span><span class="nt">/></span> |
| <span class="nt"><validator</span> <span class="na">name=</span><span class="s">"long"</span> <span class="na">class=</span><span class="s">"com.opensymphony.xwork2.validator.validators.LongRangeFieldValidator"</span><span class="nt">/></span> |
| <span class="nt"><validator</span> <span class="na">name=</span><span class="s">"short"</span> <span class="na">class=</span><span class="s">"com.opensymphony.xwork2.validator.validators.ShortRangeFieldValidator"</span><span class="nt">/></span> |
| <span class="nt"><validator</span> <span class="na">name=</span><span class="s">"double"</span> <span class="na">class=</span><span class="s">"com.opensymphony.xwork2.validator.validators.DoubleRangeFieldValidator"</span><span class="nt">/></span> |
| <span class="nt"><validator</span> <span class="na">name=</span><span class="s">"date"</span> <span class="na">class=</span><span class="s">"com.opensymphony.xwork2.validator.validators.DateRangeFieldValidator"</span><span class="nt">/></span> |
| <span class="nt"><validator</span> <span class="na">name=</span><span class="s">"expression"</span> <span class="na">class=</span><span class="s">"com.opensymphony.xwork2.validator.validators.ExpressionValidator"</span><span class="nt">/></span> |
| <span class="nt"><validator</span> <span class="na">name=</span><span class="s">"fieldexpression"</span> <span class="na">class=</span><span class="s">"com.opensymphony.xwork2.validator.validators.FieldExpressionValidator"</span><span class="nt">/></span> |
| <span class="nt"><validator</span> <span class="na">name=</span><span class="s">"email"</span> <span class="na">class=</span><span class="s">"com.opensymphony.xwork2.validator.validators.EmailValidator"</span><span class="nt">/></span> |
| <span class="nt"><validator</span> <span class="na">name=</span><span class="s">"creditcard"</span> <span class="na">class=</span><span class="s">"com.opensymphony.xwork2.validator.validators.CreditCardValidator"</span><span class="nt">/></span> |
| <span class="nt"><validator</span> <span class="na">name=</span><span class="s">"url"</span> <span class="na">class=</span><span class="s">"com.opensymphony.xwork2.validator.validators.URLValidator"</span><span class="nt">/></span> |
| <span class="nt"><validator</span> <span class="na">name=</span><span class="s">"visitor"</span> <span class="na">class=</span><span class="s">"com.opensymphony.xwork2.validator.validators.VisitorFieldValidator"</span><span class="nt">/></span> |
| <span class="nt"><validator</span> <span class="na">name=</span><span class="s">"conversion"</span> <span class="na">class=</span><span class="s">"com.opensymphony.xwork2.validator.validators.ConversionErrorFieldValidator"</span><span class="nt">/></span> |
| <span class="nt"><validator</span> <span class="na">name=</span><span class="s">"stringlength"</span> <span class="na">class=</span><span class="s">"com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator"</span><span class="nt">/></span> |
| <span class="nt"><validator</span> <span class="na">name=</span><span class="s">"regex"</span> <span class="na">class=</span><span class="s">"com.opensymphony.xwork2.validator.validators.RegexFieldValidator"</span><span class="nt">/></span> |
| <span class="nt"><validator</span> <span class="na">name=</span><span class="s">"conditionalvisitor"</span> <span class="na">class=</span><span class="s">"com.opensymphony.xwork2.validator.validators.ConditionalVisitorFieldValidator"</span><span class="nt">/></span> |
| <span class="nt"></validators></span> |
| <span class="c"><!-- END SNIPPET: validators-default --></span></code></pre></figure> |
| |
| <blockquote> |
| <p><strong>Struts 2.1 and Prior</strong> |
| The <code class="language-plaintext highlighter-rouge">validators.xml</code> used to reference a DTD hosted by Opensymphony, the original location of the XWork project. |
| Since they moved to Apache Struts, DTDs were changed. Please ensure in your projects to include the DTD header |
| as described in the examples found here.</p> |
| </blockquote> |
| |
| <blockquote> |
| <p><strong>Struts 2.0.7 and Prior</strong> |
| The <code class="language-plaintext highlighter-rouge">validators.xml</code> containing custom validators needs to contain a copy of the default validators. No DTD was used |
| in <code class="language-plaintext highlighter-rouge">validators.xml</code>. See: <a href="https://cwiki.apache.org/confluence/display/WW/Release+Notes+2.0.8#ReleaseNotes2.0.8-MigrationfrompreviousReleases">Release Notes 2.0.8</a></p> |
| </blockquote> |
| |
| <h2 id="turning-on-validation">Turning on Validation</h2> |
| |
| <p>The default interceptor stack, “defaultStack”, already has validation turned on. When creating your own interceptor-stack |
| be sure to include <strong>both</strong> the <code class="language-plaintext highlighter-rouge">validation</code> and <code class="language-plaintext highlighter-rouge">workflow</code> interceptors. From <code class="language-plaintext highlighter-rouge">struts-default.xml</code>:</p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><interceptor-stack</span> <span class="na">name=</span><span class="s">"defaultStack"</span><span class="nt">></span> |
| ... |
| <span class="nt"><interceptor-ref</span> <span class="na">name=</span><span class="s">"validation"</span><span class="nt">></span> |
| <span class="nt"><param</span> <span class="na">name=</span><span class="s">"excludeMethods"</span><span class="nt">></span>input,back,cancel,browse<span class="nt"></param></span> |
| <span class="nt"></interceptor-ref></span> |
| <span class="nt"><interceptor-ref</span> <span class="na">name=</span><span class="s">"workflow"</span><span class="nt">></span> |
| <span class="nt"><param</span> <span class="na">name=</span><span class="s">"excludeMethods"</span><span class="nt">></span>input,back,cancel,browse<span class="nt"></param></span> |
| <span class="nt"></interceptor-ref></span> |
| <span class="nt"></interceptor-stack></span> |
| </code></pre></div></div> |
| |
| <p>Beginning with version 2.0.4 Struts provides an extension to XWork’s <code class="language-plaintext highlighter-rouge">com.opensymphony.xwork2.validator.ValidationInterceptor</code> |
| interceptor.</p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><interceptor</span> <span class="na">name=</span><span class="s">"validation"</span> <span class="na">class=</span><span class="s">"org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"</span><span class="nt">/></span> |
| </code></pre></div></div> |
| |
| <p>This interceptor allows us to turn off validation for a specific method by using the <code class="language-plaintext highlighter-rouge">@org.apache.struts2.interceptor.validation.SkipValidation</code> |
| annotation on the action method.</p> |
| |
| <h2 id="validator-scopes">Validator Scopes</h2> |
| |
| <p>Field validators, as the name indicate, act on single fields accessible through an action. A validator, in contrast, |
| is more generic and can do validations in the full action context, involving more than one field (or even no field |
| at all) in validation rule. Most validations can be defined on per field basis. This should be preferred over non-field |
| validation wherever possible, as field validator messages are bound to the related field and will be presented next |
| to the corresponding input element in the respecting view.</p> |
| |
| <p>Non-field validators only add action level messages. Non-field validators are mostly domain specific and therefore |
| offer custom implementations. The most important standard non-field validator provided by XWork is <code class="language-plaintext highlighter-rouge">ExpressionValidator</code>.</p> |
| |
| <h2 id="notes">Notes</h2> |
| |
| <p>Non-field validators takes precedence over field validators regardless of the order they are defined in <code class="language-plaintext highlighter-rouge">*-validation.xml</code>. |
| If a non-field validator is <code class="language-plaintext highlighter-rouge">short-circuited</code>, it will causes its non-field validator to not being executed. |
| See validation framework documentation for more info.</p> |
| |
| <h2 id="defining-validation-rules">Defining Validation Rules</h2> |
| |
| <p>Validation rules can be specified:</p> |
| <ol> |
| <li>Per Action class: in a file named <code class="language-plaintext highlighter-rouge">ActionName-validation.xml</code></li> |
| <li>Per Action alias: in a file named <code class="language-plaintext highlighter-rouge">ActionName-alias-validation.xml</code></li> |
| <li>Inheritance hierarchy and interfaces implemented by Action class: |
| XWork searches up the inheritance tree of the action to find default |
| validations for parent classes of the Action and interfaces implemented</li> |
| </ol> |
| |
| <p>Here is an example for SimpleAction-validation.xml:</p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN" |
| "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"></span> |
| <span class="nt"><validators></span> |
| <span class="nt"><field</span> <span class="na">name=</span><span class="s">"bar"</span><span class="nt">></span> |
| <span class="nt"><field-validator</span> <span class="na">type=</span><span class="s">"required"</span><span class="nt">></span> |
| <span class="nt"><message></span>You must enter a value for bar.<span class="nt"></message></span> |
| <span class="nt"></field-validator></span> |
| <span class="nt"><field-validator</span> <span class="na">type=</span><span class="s">"int"</span><span class="nt">></span> |
| <span class="nt"><param</span> <span class="na">name=</span><span class="s">"min"</span><span class="nt">></span>6<span class="nt"></param></span> |
| <span class="nt"><param</span> <span class="na">name=</span><span class="s">"max"</span><span class="nt">></span>10<span class="nt"></param></span> |
| <span class="nt"><message></span>bar must be between ${min} and ${max}, current value is ${bar}.<span class="nt"></message></span> |
| <span class="nt"></field-validator></span> |
| <span class="nt"></field></span> |
| <span class="nt"><field</span> <span class="na">name=</span><span class="s">"bar2"</span><span class="nt">></span> |
| <span class="nt"><field-validator</span> <span class="na">type=</span><span class="s">"regex"</span><span class="nt">></span> |
| <span class="nt"><param</span> <span class="na">name=</span><span class="s">"expression"</span><span class="nt">></span>[0-9],[0-9]<span class="nt"></param></span> |
| <span class="nt"><message></span>The value of bar2 must be in the format "x, y", where x and y are between 0 and 9<span class="nt"></message></span> |
| <span class="nt"></field-validator></span> |
| <span class="nt"></field></span> |
| <span class="nt"><field</span> <span class="na">name=</span><span class="s">"date"</span><span class="nt">></span> |
| <span class="nt"><field-validator</span> <span class="na">type=</span><span class="s">"date"</span><span class="nt">></span> |
| <span class="nt"><param</span> <span class="na">name=</span><span class="s">"min"</span><span class="nt">></span>12/22/2002<span class="nt"></param></span> |
| <span class="nt"><param</span> <span class="na">name=</span><span class="s">"max"</span><span class="nt">></span>12/25/2002<span class="nt"></param></span> |
| <span class="nt"><message></span>The date must be between 12-22-2002 and 12-25-2002.<span class="nt"></message></span> |
| <span class="nt"></field-validator></span> |
| <span class="nt"></field></span> |
| <span class="nt"><field</span> <span class="na">name=</span><span class="s">"foo"</span><span class="nt">></span> |
| <span class="nt"><field-validator</span> <span class="na">type=</span><span class="s">"int"</span><span class="nt">></span> |
| <span class="nt"><param</span> <span class="na">name=</span><span class="s">"min"</span><span class="nt">></span>0<span class="nt"></param></span> |
| <span class="nt"><param</span> <span class="na">name=</span><span class="s">"max"</span><span class="nt">></span>100<span class="nt"></param></span> |
| <span class="nt"><message</span> <span class="na">key=</span><span class="s">"foo.range"</span><span class="nt">></span>Could not find foo.range!<span class="nt"></message></span> |
| <span class="nt"></field-validator></span> |
| <span class="nt"></field></span> |
| <span class="nt"><validator</span> <span class="na">type=</span><span class="s">"expression"</span><span class="nt">></span> |
| <span class="nt"><param</span> <span class="na">name=</span><span class="s">"expression"</span><span class="nt">></span>foo lt bar <span class="nt"></param></span> |
| <span class="nt"><message></span>Foo must be greater than Bar. Foo = ${foo}, Bar = ${bar}.<span class="nt"></message></span> |
| <span class="nt"></validator></span> |
| <span class="nt"></validators></span> |
| </code></pre></div></div> |
| |
| <p>Here we can see the configuration of validators for the <code class="language-plaintext highlighter-rouge">SimpleActio</code>n class. Validators (and field-validators) must have |
| a <code class="language-plaintext highlighter-rouge">type</code> attribute, which refers to a name of an Validator registered with the <code class="language-plaintext highlighter-rouge">ValidatorFactory </code>as above. Validator elements |
| may also have <code class="language-plaintext highlighter-rouge"><param></code> elements with name and value attributes to set arbitrary parameters into the Validator instance. |
| See below for discussion of the message element.</p> |
| |
| <p>In this context, “Action Alias” refers to the action name as given in the Struts configuration. Often, the name attribute |
| matches the method name, but they may also differ.</p> |
| |
| <h2 id="localizing-and-parameterizing-messages">Localizing and Parameterizing Messages</h2> |
| |
| <p>Each Validator or Field-Validator element must define one message element inside the validator element body. The message |
| element has 1 attributes, key which is not required. The body of the message tag is taken as the default message which |
| should be added to the Action if the validator fails. Key gives a message key to look up in the Action’s ResourceBundles |
| using <code class="language-plaintext highlighter-rouge">getText()</code> from <code class="language-plaintext highlighter-rouge">LocaleAware</code> if the Action implements that interface (as <code class="language-plaintext highlighter-rouge">ActionSupport</code> does). This provides |
| for Localized messages based on the <code class="language-plaintext highlighter-rouge">Locale</code> of the user making the request (or whatever <code class="language-plaintext highlighter-rouge">Locale</code> you’ve set into |
| the <code class="language-plaintext highlighter-rouge">LocaleAware</code> Action). After either retrieving the message from the ResourceBundle using the Key value, or using |
| the Default message, the current Validator is pushed onto the ValueStack, then the message is parsed for <code class="language-plaintext highlighter-rouge">${...}</code> |
| sections which are replaced with the evaluated value of the string between the <code class="language-plaintext highlighter-rouge">${</code> and <code class="language-plaintext highlighter-rouge">}</code>. This allows you |
| to parameterize your messages with values from the Validator, the Action, or both.</p> |
| |
| <p>If the validator fails, the validator is pushed onto the ValueStack and the message - either the default or |
| the locale-specific one if the key attribute is defined (and such a message exists) - is parsed for <code class="language-plaintext highlighter-rouge">${...}</code> sections |
| which are replaced with the evaluated value of the string between the <code class="language-plaintext highlighter-rouge">${</code> and <code class="language-plaintext highlighter-rouge">}</code>. This allows you to parameterize |
| your messages with values from the validator, the Action, or both.</p> |
| |
| <blockquote> |
| <p>Since validation rules are in an XML file, you must make sure you escape special characters. For example, notice |
| that in the expression validator rule above we use “>” instead of “>”. Consult a resource on XML |
| for the full list of characters that must be escaped. The most commonly used characters that must be escaped |
| are: & (use &), < (use <), and > (use >).</p> |
| </blockquote> |
| |
| <p>Here is an example of a parameterized message:</p> |
| |
| <p>This will pull the min and max parameters from the IntRangeFieldValidator and the value of bar from the Action.</p> |
| |
| <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>bar must be between ${min} and ${max}, current value is ${bar}. |
| </code></pre></div></div> |
| |
| <p>Another notable fact is that the provided message value is capable of containing OGNL expressions. Keeping this in mind, |
| it is possible to construct quite sophisticated messages.</p> |
| |
| <p>See the following example to get an impression:</p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><message></span>${getText("validation.failednotice")} ! ${getText("reason")}: ${getText("validation.inputrequired")}<span class="nt"></message></span> |
| </code></pre></div></div> |
| |
| <h3 id="customizing-validation-messages">Customizing validation messages</h3> |
| |
| <p>There is another option to customise validation messages by using parametrized messages. Either you can use them via |
| XML or with annotations.</p> |
| |
| <h4 id="xml">XML</h4> |
| |
| <p>To use this new approach you must use a proper header in a <code class="language-plaintext highlighter-rouge"><ActionName>-validation.xml</code> file, see below:</p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?xml version="1.0"?></span> |
| <span class="cp"><!DOCTYPE validators PUBLIC |
| "-//Apache Struts//XWork Validator 1.0.3//EN" |
| "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"></span> |
| <span class="nt"><validators></span> |
| ... |
| <span class="nt"></validators></span> |
| </code></pre></div></div> |
| |
| <p>Now you can define validators that will use parametrized messages as below:</p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><field</span> <span class="na">name=</span><span class="s">"username"</span><span class="nt">></span> |
| <span class="nt"><field-validator</span> <span class="na">type=</span><span class="s">"requiredstring"</span><span class="nt">></span> |
| <span class="nt"><message</span> <span class="na">key=</span><span class="s">"errors.required"</span><span class="nt">></span> |
| <span class="nt"><param</span> <span class="na">name=</span><span class="s">"0"</span><span class="nt">></span>getText('username.field.name')<span class="nt"></param></span> |
| <span class="nt"></message></span> |
| <span class="nt"></field-validator></span> |
| <span class="nt"></field></span> |
| </code></pre></div></div> |
| |
| <blockquote> |
| <p>NOTE: Please be aware that all the parameters will be evaluated against <code class="language-plaintext highlighter-rouge">ValueStack</code>, please do not reference user |
| controlled values or incoming parameters in request as this can lead to a security vulnerability</p> |
| </blockquote> |
| |
| <p>Now you can define your properties file with localized messages:</p> |
| |
| <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>errors.required={0} is required. |
| username.field.name=Username |
| </code></pre></div></div> |
| |
| <p>As you can see you defined a <code class="language-plaintext highlighter-rouge">errors.required</code> key with a placeholder for the param. The names of the params are not important, |
| order is important as this mechanism uses <code class="language-plaintext highlighter-rouge">MessageFormat</code> to format the message.</p> |
| |
| <p>The final output will be as follow:</p> |
| |
| <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Username is required. |
| </code></pre></div></div> |
| |
| <h4 id="annotations">Annotations</h4> |
| |
| <p>The same mechanism can be used with annotations as follow:</p> |
| |
| <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@RequiredStringValidator</span><span class="o">(</span><span class="n">key</span> <span class="o">=</span> <span class="s">"errors.required"</span><span class="o">,</span> <span class="n">messageParams</span> <span class="o">=</span> <span class="o">{</span> |
| <span class="s">"getText('username.field.name')"</span> |
| <span class="o">})</span> |
| <span class="nd">@StrutsParameter</span> |
| <span class="kd">public</span> <span class="kt">void</span> <span class="nf">setUsername</span><span class="o">(</span><span class="nc">String</span> <span class="n">username</span><span class="o">)</span> <span class="o">{</span> |
| <span class="k">this</span><span class="o">.</span><span class="na">username</span> <span class="o">=</span> <span class="n">username</span><span class="o">;</span> |
| <span class="o">}</span> |
| </code></pre></div></div> |
| |
| <h2 id="validator-flavor">Validator Flavor</h2> |
| |
| <p>The validators supplied by the XWork distribution (and any validators you might write yourself) come in two different |
| flavors:</p> |
| |
| <ol> |
| <li>Plain Validators / Non-Field validators</li> |
| <li>FieldValidators</li> |
| </ol> |
| |
| <p>Plain Validators (such as the <code class="language-plaintext highlighter-rouge">ExpressionValidator</code>) perform validation checks that are not inherently tied to a single |
| specified field. When you declare a plain Validator in your <code class="language-plaintext highlighter-rouge">-validation.xml</code> file you do not associate a <code class="language-plaintext highlighter-rouge">fieldname</code> |
| attribute with it. You should avoid using plain Validators within the <code class="language-plaintext highlighter-rouge"><field-validator></code> syntax described below.</p> |
| |
| <p>FieldValidators (such as the <code class="language-plaintext highlighter-rouge">EmailValidator</code>) are designed to perform validation checks on a single field. They require |
| that you specify a <code class="language-plaintext highlighter-rouge">fieldname</code> attribute in your <code class="language-plaintext highlighter-rouge">-validation.xml</code> file. There are two different (but equivalent) |
| XML syntaxes you can use to declare FieldValidators (see “<validator> vs. <field-Validator> syntax" below).</field-Validator></validator></p> |
| |
| <p>There are two places where the differences between the two validator flavors are important to keep in mind:</p> |
| |
| <ol> |
| <li>when choosing the xml syntax used for declaring a validator (either <code class="language-plaintext highlighter-rouge"><validator></code> or <code class="language-plaintext highlighter-rouge"><field-validator></code>)</li> |
| <li>when using the <code class="language-plaintext highlighter-rouge">short-circuit</code> capability</li> |
| </ol> |
| |
| <blockquote> |
| <p>Note that you do not declare what “flavor” of validator you are using in your <code class="language-plaintext highlighter-rouge">-validation.xml</code> file, you just declare |
| the name of the validator to use and Struts will know whether it’s a “plain Validator” or a “FieldValidator” |
| by looking at the validation class that the validator’s programmer chose to implement.</p> |
| </blockquote> |
| |
| <h2 id="non-field-validator-vs-field-validator-validatortypes">Non-Field Validator Vs Field-Validator validatortypes</h2> |
| |
| <p>There are two ways you can define validators in your <code class="language-plaintext highlighter-rouge">-validation.xml</code> file:</p> |
| |
| <ol> |
| <li><code class="language-plaintext highlighter-rouge"><validator></code></li> |
| <li><code class="language-plaintext highlighter-rouge"><field-validator></code></li> |
| </ol> |
| |
| <p>Keep the following in mind when using either syntax:</p> |
| |
| <p>Non-Field-Validator: The <code class="language-plaintext highlighter-rouge"><validator></code> element allows you to declare both types of validators (either a plain Validator |
| a field-specific FieldValidator).</p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><validator</span> <span class="na">type=</span><span class="s">"expression"</span><span class="nt">></span> |
| <span class="nt"><param</span> <span class="na">name=</span><span class="s">"expression"</span><span class="nt">></span>foo gt bar<span class="nt"></param></span> |
| <span class="nt"><message></span>foo must be great than bar.<span class="nt"></message></span> |
| <span class="nt"></validator></span> |
| </code></pre></div></div> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><validator</span> <span class="na">type=</span><span class="s">"required"</span><span class="nt">></span> |
| <span class="nt"><param</span> <span class="na">name=</span><span class="s">"fieldName"</span><span class="nt">></span>bar<span class="nt"></param></span> |
| <span class="nt"><message></span>You must enter a value for bar.<span class="nt"></message></span> |
| <span class="nt"></validator></span> |
| </code></pre></div></div> |
| |
| <p><strong>field-validator</strong>: The <code class="language-plaintext highlighter-rouge"><field-validator></code> elements are basically the same as the <code class="language-plaintext highlighter-rouge"><validator></code> elements except that |
| they inherit the <code class="language-plaintext highlighter-rouge">fieldName</code> attribute from the enclosing <code class="language-plaintext highlighter-rouge"><field></code> element. FieldValidators defined within a <code class="language-plaintext highlighter-rouge"><field-validator</code>> |
| element will have their <code class="language-plaintext highlighter-rouge">fieldName</code> automatically filled with the value of the parent <code class="language-plaintext highlighter-rouge"><field></code> element’s <code class="language-plaintext highlighter-rouge">fieldName</code> |
| attribute. The reason for this structure is to conveniently group the validators for a particular field under one element, |
| otherwise the fieldName attribute would have to be repeated, over and over, for each individual <code class="language-plaintext highlighter-rouge"><validator></code>.</p> |
| |
| <p>It is always better to defined field-validator inside a <code class="language-plaintext highlighter-rouge"><field></code> tag instead of using a <code class="language-plaintext highlighter-rouge"><validator></code> tag and supplying |
| <code class="language-plaintext highlighter-rouge">fieldName</code> as its param as the xml code itself is clearer (grouping of field is clearer).</p> |
| |
| <blockquote> |
| <p>Note that you should only use FieldValidators (not plain Validators) within a block. A plain Validator inside |
| a <code class="language-plaintext highlighter-rouge"><field></code> will not be allowed and would generate error when parsing the xml, as it is not allowed |
| in the defined DTD (xwork-validator-1.0.2.dtd)</p> |
| </blockquote> |
| |
| <p>Declaring a FieldValidator using the <code class="language-plaintext highlighter-rouge"><field-validator></code> syntax:</p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><field</span> <span class="na">name=</span><span class="s">"email_address"</span><span class="nt">></span> |
| <span class="nt"><field-validator</span> <span class="na">type=</span><span class="s">"required"</span><span class="nt">></span> |
| <span class="nt"><message></span>You cannot leave the email address field empty.<span class="nt"></message></span> |
| <span class="nt"></field-validator></span> |
| <span class="nt"><field-validator</span> <span class="na">type=</span><span class="s">"email"</span><span class="nt">></span> |
| <span class="nt"><message></span>The email address you entered is not valid.<span class="nt"></message></span> |
| <span class="nt"></field-validator></span> |
| <span class="nt"></field></span> |
| </code></pre></div></div> |
| |
| <p>The choice is yours. It’s perfectly legal to only use elements without the elements and set the <code class="language-plaintext highlighter-rouge">fieldName</code> attribute |
| for each of them. The following are effectively equal:</p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><field</span> <span class="na">name=</span><span class="s">"email_address"</span><span class="nt">></span> |
| <span class="nt"><field-validator</span> <span class="na">type=</span><span class="s">"required"</span><span class="nt">></span> |
| <span class="nt"><message></span>You cannot leave the email address field empty.<span class="nt"></message></span> |
| <span class="nt"></field-validator></span> |
| <span class="nt"><field-validator</span> <span class="na">type=</span><span class="s">"email"</span><span class="nt">></span> |
| <span class="nt"><message></span>The email address you entered is not valid.<span class="nt"></message></span> |
| <span class="nt"></field-validator></span> |
| <span class="nt"></field></span> |
| |
| <span class="nt"><validator</span> <span class="na">type=</span><span class="s">"required"</span><span class="nt">></span> |
| <span class="nt"><param</span> <span class="na">name=</span><span class="s">"fieldName"</span><span class="nt">></span>email_address<span class="nt"></param></span> |
| <span class="nt"><message></span>You cannot leave the email address field empty.<span class="nt"></message></span> |
| <span class="nt"></validator></span> |
| <span class="nt"><validator</span> <span class="na">type=</span><span class="s">"email"</span><span class="nt">></span> |
| <span class="nt"><param</span> <span class="na">name=</span><span class="s">"fieldName"</span><span class="nt">></span>email_address<span class="nt"></param></span> |
| <span class="nt"><message></span>The email address you entered is not valid.<span class="nt"></message></span> |
| <span class="nt"></validator></span> |
| </code></pre></div></div> |
| |
| <h2 id="short-circuiting-validator">Short-Circuiting Validator</h2> |
| |
| <p>It is possible to <code class="language-plaintext highlighter-rouge">short-circuit</code> a stack of validators. Here is another sample config file containing validation |
| rules from the Xwork test cases: Notice that some of the <code class="language-plaintext highlighter-rouge"><field-validator></code> and <code class="language-plaintext highlighter-rouge"><validator></code> elements have |
| the <code class="language-plaintext highlighter-rouge">short-circuit</code> attribute set to true.</p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE validators PUBLIC |
| "-//Apache Struts//XWork Validator 1.0.3//EN" |
| "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"></span> |
| <span class="nt"><validators></span> |
| <span class="c"><!-- Field Validators for email field --></span> |
| <span class="nt"><field</span> <span class="na">name=</span><span class="s">"email"</span><span class="nt">></span> |
| <span class="nt"><field-validator</span> <span class="na">type=</span><span class="s">"required"</span> <span class="na">short-circuit=</span><span class="s">"true"</span><span class="nt">></span> |
| <span class="nt"><message></span>You must enter a value for email.<span class="nt"></message></span> |
| <span class="nt"></field-validator></span> |
| <span class="nt"><field-validator</span> <span class="na">type=</span><span class="s">"email"</span> <span class="na">short-circuit=</span><span class="s">"true"</span><span class="nt">></span> |
| <span class="nt"><message></span>Not a valid e-mail.<span class="nt"></message></span> |
| <span class="nt"></field-validator></span> |
| <span class="nt"></field></span> |
| <span class="c"><!-- Field Validators for email2 field --></span> |
| <span class="nt"><field</span> <span class="na">name=</span><span class="s">"email2"</span><span class="nt">></span> |
| <span class="nt"><field-validator</span> <span class="na">type=</span><span class="s">"required"</span><span class="nt">></span> |
| <span class="nt"><message></span>You must enter a value for email2.<span class="nt"></message></span> |
| <span class="nt"></field-validator></span> |
| <span class="nt"><field-validator</span> <span class="na">type=</span><span class="s">"email"</span><span class="nt">></span> |
| <span class="nt"><message></span>Not a valid e-mail2.<span class="nt"></message></span> |
| <span class="nt"></field-validator></span> |
| <span class="nt"></field></span> |
| <span class="c"><!-- Plain Validator 1 --></span> |
| <span class="nt"><validator</span> <span class="na">type=</span><span class="s">"expression"</span><span class="nt">></span> |
| <span class="nt"><param</span> <span class="na">name=</span><span class="s">"expression"</span><span class="nt">></span>email.equals(email2)<span class="nt"></param></span> |
| <span class="nt"><message></span>Email not the same as email2<span class="nt"></message></span> |
| <span class="nt"></validator></span> |
| <span class="c"><!-- Plain Validator 2 --></span> |
| <span class="nt"><validator</span> <span class="na">type=</span><span class="s">"expression"</span> <span class="na">short-circuit=</span><span class="s">"true"</span><span class="nt">></span> |
| <span class="nt"><param</span> <span class="na">name=</span><span class="s">"expression"</span><span class="nt">></span>email.startsWith('mark')<span class="nt"></param></span> |
| <span class="nt"><message></span>Email does not start with mark<span class="nt"></message></span> |
| <span class="nt"></validator></span> |
| <span class="nt"></validators></span> |
| </code></pre></div></div> |
| |
| <p><strong>short-circuiting and Validator flavors</strong></p> |
| |
| <p>Plain validator takes precedence over field-validator. They get validated first in the order they are defined and then |
| the field-validator in the order they are defined. Failure of a particular validator marked as short-circuit will |
| prevent the evaluation of subsequent validators and an error (action error or field error depending on the type of validator) |
| will be added to the <code class="language-plaintext highlighter-rouge">ValidationContext</code> of the object being validated.</p> |
| |
| <p>In the example above, the actual execution of validator would be as follows:</p> |
| |
| <ol> |
| <li>Plain Validator 1</li> |
| <li>Plain Validator 2</li> |
| <li>Field Validators for email field</li> |
| <li>Field Validators for email2 field</li> |
| </ol> |
| |
| <p>Since Plain Validator 2 is short-circuited, if its validation failed, it will causes Field validators for email field |
| and Field validators for email2 field to not be validated as well.</p> |
| |
| <p><strong>Usefull Information:</strong> |
| More complicated validation should probably be done in the <code class="language-plaintext highlighter-rouge">validate()</code> method on the action itself (assuming the action |
| implements <code class="language-plaintext highlighter-rouge">Validatable</code> interface which <code class="language-plaintext highlighter-rouge">ActionSupport</code> already does).</p> |
| |
| <p>A plain Validator (non FieldValidator) that gets short-circuited will completely break out of the validation stack. |
| No other validators will be evaluated and plain validators takes precedence over field validators meaning that they |
| get evaluated in the order they are defined before field validators get a chance to be evaluated.</p> |
| |
| <p><strong>Short cuircuiting and validator flavours</strong></p> |
| |
| <p>A FieldValidator that gets short-circuited will only prevent other FieldValidators for the same field from being |
| evaluated. Note that this “same field” behavior applies regardless of whether the <code class="language-plaintext highlighter-rouge"><validator></code> or <code class="language-plaintext highlighter-rouge"><field-validator></code> |
| syntax was used to declare the validation rule. By way of example, given this <code class="language-plaintext highlighter-rouge">-validation.xml</code> file:</p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><validator</span> <span class="na">type=</span><span class="s">"required"</span> <span class="na">short-circuit=</span><span class="s">"true"</span><span class="nt">></span> |
| <span class="nt"><param</span> <span class="na">name=</span><span class="s">"fieldName"</span><span class="nt">></span>bar<span class="nt"></param></span> |
| <span class="nt"><message></span>You must enter a value for bar.<span class="nt"></message></span> |
| <span class="nt"></validator></span> |
| |
| <span class="nt"><validator</span> <span class="na">type=</span><span class="s">"expression"</span><span class="nt">></span> |
| <span class="nt"><param</span> <span class="na">name=</span><span class="s">"expression"</span><span class="nt">></span>foo gt bar<span class="nt"></param></span> |
| <span class="nt"><message></span>foo must be great than bar.<span class="nt"></message></span> |
| <span class="nt"></validator></span> |
| </code></pre></div></div> |
| |
| <p>both validators will be run, even if the “required” validator short-circuits. “required” validators are FieldValidator’s |
| and will not short-circuit the plain ExpressionValidator because FieldValidators only short-circuit other checks on that |
| same field. Since the plain Validator is not field specific, it is not short-circuited.</p> |
| |
| <h2 id="how-validators-of-an-action-are-found">How Validators of an Action are Found</h2> |
| |
| <p>As mentioned above, the framework will also search up the inheritance tree of the action to find default validations |
| for interfaces and parent classes of the Action. If you are using the short-circuit attribute and relying on default |
| validators higher up in the inheritance tree, make sure you don’t accidentally short-circuit things higher in the tree |
| that you really want!</p> |
| |
| <p>The effect of having common validators on both</p> |
| |
| <ul> |
| <li><code class="language-plaintext highlighter-rouge"><actionClass>-validation.xml</code></li> |
| <li><code class="language-plaintext highlighter-rouge"><actionClass>-<actionAlias>-validation.xml</code></li> |
| </ul> |
| |
| <p>It should be noted that the nett effect will be validation on both the validators available in both validation |
| configuration file. For example if we have ‘requiredstring’ validators defined in both validation xml file for field |
| named ‘address’, we will see 2 validation error indicating that the the address cannot be empty (assuming validation |
| failed). This is due to WebWork will merge validators found in both validation configuration files.</p> |
| |
| <p>The logic behind this design decision is such that we could have common validators in <code class="language-plaintext highlighter-rouge"><actionClass>-validation.xml</code> |
| and more context specific validators to be located in <code class="language-plaintext highlighter-rouge"><actionClass>-<actionAlias>-validation.xml</code>.</p> |
| |
| <h2 id="writing-custom-validators">Writing custom validators</h2> |
| |
| <p>If you want to write custom validator use on of these classes as a starting point:</p> |
| |
| <ul> |
| <li><code class="language-plaintext highlighter-rouge">com.opensymphony.xwork2.validator.validators.ValidatorSupport</code></li> |
| <li><code class="language-plaintext highlighter-rouge">com.opensymphony.xwork2.validator.validators.FieldValidatorSupport</code></li> |
| <li><code class="language-plaintext highlighter-rouge">com.opensymphony.xwork2.validator.validators.RangeValidatorSupport</code></li> |
| <li><code class="language-plaintext highlighter-rouge">com.opensymphony.xwork2.validator.validators.RepopulateConversionErrorFieldValidatorSupport</code></li> |
| </ul> |
| |
| <h2 id="resources">Resources</h2> |
| |
| <p><a href="http://today.java.net/pub/a/today/2006/01/19/webwork-validation">WebWork Validation</a></p> |
| |
| </section> |
| </article> |
| |
| |
| <footer class="container"> |
| <div class="col-md-12"> |
| Copyright © 2000-2022 <a href="https://www.apache.org/">The Apache Software Foundation</a>. |
| Apache Struts, Struts, Apache, the Apache feather logo, and the Apache Struts project logos are |
| trademarks of The Apache Software Foundation. All Rights Reserved. |
| </div> |
| <div class="col-md-12">Logo and website design donated by <a href="https://softwaremill.com/">SoftwareMill</a>.</div> |
| </footer> |
| |
| <script>!function (d, s, id) { |
| var js, fjs = d.getElementsByTagName(s)[0]; |
| if (!d.getElementById(id)) { |
| js = d.createElement(s); |
| js.id = id; |
| js.src = "//platform.twitter.com/widgets.js"; |
| fjs.parentNode.insertBefore(js, fjs); |
| } |
| }(document, "script", "twitter-wjs");</script> |
| <script src="https://apis.google.com/js/platform.js" async="async" defer="defer"></script> |
| |
| <div id="fb-root"></div> |
| |
| <script>(function (d, s, id) { |
| var js, fjs = d.getElementsByTagName(s)[0]; |
| if (d.getElementById(id)) return; |
| js = d.createElement(s); |
| js.id = id; |
| js.src = "//connect.facebook.net/en_GB/all.js#xfbml=1"; |
| fjs.parentNode.insertBefore(js, fjs); |
| }(document, 'script', 'facebook-jssdk'));</script> |
| |
| |
| </body> |
| </html> |