blob: e6ac8701d96a1ab2bf7135e6dbc8cb126b7413f4 [file] [log] [blame]
<!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>OVal Plugin</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="/highlighter/github-theme.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>
</head>
<body>
<a href="http://github.com/apache/struts" class="github-ribbon">
<img style="position: absolute; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png" alt="Fork me on GitHub">
</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-2021.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>
</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 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><a href="/contributors/">Contributors Guide</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="https://cwiki.apache.org/confluence/display/WW/Contributors+Guide">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/plugins/oval/index.md" title="Edit this page on GitHub">Edit on GitHub</a>
<a href="../" title="back to Plugins"><< back to Plugins</a>
<h1 id="oval-plugin">OVal Plugin</h1>
<h2 id="overview">Overview</h2>
<p><a href="http://oval.sourceforge.net/">OVal</a> is a pragmatic and extensible validation framework for any kind of Java objects (not only JavaBeans). Constraints can be declared with annotations (@NotNull, @MaxLength), POJOs or XML. Custom constraints can be expressed as custom Java classes or by using scripting languages such as JavaScript, Groovy, BeanShell, OGNL or MVEL.</p>
<p>The OVal plugin provides support for using the <a href="http://oval.sourceforge.net/">OVal Validation Framework</a></p>
<h2 id="interceptors">Interceptors</h2>
<p>The plugin defines the interceptor “ovalValidation” and the interceptor stack “ovalValidationStack” in the “oval-default” package. To use this interceptor, extend the “oval-default” package and apply the interceptor to your action, like:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;struts&gt;</span>
<span class="nt">&lt;package</span> <span class="na">namespace=</span><span class="s">"/myactions"</span> <span class="na">name=</span><span class="s">"myactions"</span> <span class="na">extends=</span><span class="s">"oval-default"</span><span class="nt">&gt;</span>
<span class="nt">&lt;action</span> <span class="na">name=</span><span class="s">"simpleFieldsXMLChild"</span> <span class="na">class=</span><span class="s">"org.apache.struts2.interceptor.SimpleFieldsXMLChild"</span><span class="nt">&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"ovalValidationStack"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;result</span> <span class="na">type=</span><span class="s">"void"</span><span class="nt">&gt;&lt;/result&gt;</span>
<span class="nt">&lt;/action&gt;</span>
<span class="nt">&lt;/package&gt;</span>
<span class="nt">&lt;/struts&gt;</span>
</code></pre></div></div>
<h2 id="annotations">Annotations</h2>
<p>OVal provides many annotations for validations that can be used out of the box (custom validators can also be defined). Once the “ovalValidation” interceptor is applied to an action, you can annotate it:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">SimpleField</span> <span class="kd">extends</span> <span class="n">ActionSupport</span><span class="o">{</span>
<span class="nd">@NotNull</span><span class="o">()</span>
<span class="nd">@NotEmpty</span>
<span class="nd">@Length</span><span class="o">(</span><span class="n">max</span> <span class="o">=</span> <span class="mi">3</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">name</span><span class="o">;</span>
<span class="c1">//...</span>
<span class="o">}</span>
</code></pre></div></div>
<p>Use the @AssertValid annotation to validate nested objects, like</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">MemberObject</span> <span class="kd">extends</span> <span class="n">ActionSupport</span> <span class="o">{</span>
<span class="nd">@AssertValid</span>
<span class="kd">private</span> <span class="n">Person</span> <span class="n">person</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Person</span><span class="o">();</span>
<span class="kd">public</span> <span class="n">Person</span> <span class="nf">getPerson</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">person</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<h2 id="xml-configuration">XML Configuration</h2>
<p>OVal provides support for defining the validation via XML. Validation files must end in “-validation.xml” and the rules to find them, are the same rules used to find the validation XML files used by the regular validation mechanisms (default validation in xwork):</p>
<ol>
<li>
<p>Per Action class: in a file named ActionName-validation.xml</p>
</li>
<li>
<p>Per Action alias: in a file named ActionName-alias-validation.xml</p>
</li>
<li>
<p>Inheritance hierarchy and interfaces implemented by Action class: The plugin searches up the inheritance tree of the action to find default validations for parent classes of the Action and interfaces implemented</p>
</li>
</ol>
<p>Here is an example of an XML validation file:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span>
<span class="nt">&lt;oval</span> <span class="na">xmlns=</span><span class="s">"http://oval.sf.net/oval-configuration"</span> <span class="na">xmlns:xsi=</span><span class="s">"http://http://www.w3.org/2001/XMLSchema-instance"</span>
<span class="na">xsi:schemaLocation=</span><span class="s">"http://oval.sf.net/oval-configuration http://oval.sourceforge.net/oval-configuration-1.3.xsd"</span><span class="nt">&gt;</span>
<span class="nt">&lt;class</span> <span class="na">type=</span><span class="s">"org.apache.struts2.interceptor.SimpleFieldsXML"</span> <span class="na">overwrite=</span><span class="s">"false"</span>
<span class="na">applyFieldConstraintsToSetters=</span><span class="s">"true"</span><span class="nt">&gt;</span>
<span class="nt">&lt;field</span> <span class="na">name=</span><span class="s">"firstName"</span><span class="nt">&gt;</span>
<span class="nt">&lt;notNull/&gt;</span>
<span class="nt">&lt;/field&gt;</span>
<span class="nt">&lt;/class&gt;</span>
<span class="nt">&lt;/oval&gt;</span>
</code></pre></div></div>
<h2 id="profiles">Profiles</h2>
<p>A profile is a set of validations, that can be enabled for a method in an action, for example:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">org.apache.struts2.validation.Profiles</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">FieldsWithProfiles</span> <span class="kd">extends</span> <span class="n">ActionSupport</span> <span class="o">{</span>
<span class="nd">@NotNull</span><span class="o">(</span><span class="n">profiles</span> <span class="o">=</span> <span class="s">"1"</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">firstName</span><span class="o">;</span>
<span class="nd">@NotNull</span><span class="o">(</span><span class="n">profiles</span> <span class="o">=</span> <span class="s">"2"</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">middleName</span><span class="o">;</span>
<span class="nd">@NotNull</span><span class="o">(</span><span class="n">profiles</span> <span class="o">=</span> <span class="s">"3"</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">lastName</span><span class="o">;</span>
<span class="nd">@Profiles</span><span class="o">({</span><span class="s">"1"</span><span class="o">,</span> <span class="s">"3"</span><span class="o">})</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">firstAndLast</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">SUCCESS</span><span class="o">;</span>
<span class="o">}</span>
<span class="nd">@Profiles</span><span class="o">({</span><span class="s">"2"</span><span class="o">})</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">middle</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">SUCCESS</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>In this example, when <em>firstAndLast()</em> is executed, the fields <em>firstName</em> and <em>lastName</em> will be validated. When <em>middle()</em> is executed, only <em>middleName</em> will be validated. When a method is annotated with the <em>Profiles</em> annotation, only the validations in the specified profiles will be performed. If no profile is specified for an action method, all the validations in the class will be evaluated.</p>
<h2 id="internationalization-of-messages">Internationalization of messages</h2>
<p>The OVal annotations (and corresponding XML tags) have a <em>message</em> attribute that can be used to specify either the error message, or the key of the error message. If a key is found in a property file, matching the value of the <em>massage</em> attribute, it will be used as the message, otherwise the value will be used as a literal string. For example, given this property file:</p>
<p><strong>BookAction.properties</strong></p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>notnull.field=${field.name} cannot be null
field.too.long=${field.name} value is too long, allowed length is ${max}
</code></pre></div></div>
<p>and this class:</p>
<p><strong>BookAction.java</strong></p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">BookActionextends</span> <span class="kd">extends</span> <span class="n">ActionSupport</span> <span class="o">{</span>
<span class="nd">@NotNull</span><span class="o">(</span><span class="n">message</span> <span class="o">=</span> <span class="s">"notnull.field"</span><span class="o">)</span>
<span class="nd">@Length</span><span class="o">(</span><span class="n">max</span> <span class="o">=</span> <span class="mi">3</span><span class="o">,</span> <span class="n">message</span> <span class="o">=</span> <span class="s">"field.too.long"</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">title</span><span class="o">;</span>
<span class="nd">@NotNull</span><span class="o">(</span><span class="n">message</span> <span class="o">=</span> <span class="s">"You must enter a valid ISBN"</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">isbn</span><span class="o">;</span>
<span class="c1">//...</span>
<span class="o">}</span>
</code></pre></div></div>
<p>When that action is validated, the field errors would be:</p>
<ul>
<li>
<p>“title cannot be null”</p>
</li>
<li>
<p>“You must enter a valid ISBN”</p>
</li>
<li>
<p>“title value is too long, allowed length is 3”</p>
</li>
</ul>
<p>The current OVal “context” object is pushed into the stack for each validator, so it can be accessed from the property file to build the error message. See the <a href="http://oval.sourceforge.net/api/net/sf/oval/context/FieldContext.html">OVal javadoc</a> for more properties available in the FieldContext class.</p>
<h2 id="the-oval-validation-interceptor">The OVal Validation Interceptor</h2>
<p>This interceptor runs the action through the standard validation framework, which in turn checks the action against any validation rules (found in files such as ActionClass-validation.xml) and adds field-level and action-level error messages (provided that the action implements com.opensymphony.xwork2.ValidationAware). This interceptor is often one of the last (or second to last) interceptors applied in a stack, as it assumes that all values have already been set on the action.</p>
<p>This interceptor does nothing if the name of the method being invoked is specified in the <em>excludeMethods</em> parameter. <em>excludeMethods</em> accepts a comma-delimited list of method names. For example, requests to foo!input.action and foo!back.action will be skipped by this interceptor if you set the excludeMethods parameter to “input, back”.</p>
<p>Note that this has nothing to do with the com.opensymphony.xwork2.Validateable interface and simply adds error messages to the action. The workflow of the action request does not change due to this interceptor. Rather, this interceptor is often used in conjuction with the workflow interceptor.</p>
<p>NOTE: As this method extends off MethodFilterInterceptor, it is capable of deciding if it is applicable only to selective methods in the action class. See MethodFilterInterceptor for more info.</p>
<p>The param <em>alwaysInvokeValidate</em> (default to <em>true</em> ), will make the interceptor invoke <em>validate()</em> on the action, if the action implements <em>Validateable</em> .</p>
<p>The param <em>programmatic</em> (defaults to <em>true</em> ), will make the plugin call <em>validateX()</em> where <em>X</em> is the name of the method that will be invoked in the action. If this param is set to <em>false</em> , <em>alwaysInvokeValidate</em> is ignored and <em>validate()</em> won’t be invoked.</p>
<h2 id="installation">Installation</h2>
<p>The jar plugin needs to be added to the lib directory of your application as well as other dependencies. If you are using XML validation, XStream needs to be included. Here is the maven dependency example:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;dependency&gt;</span>
<span class="nt">&lt;groupId&gt;</span>com.thoughtworks.xstream<span class="nt">&lt;/groupId&gt;</span>
<span class="nt">&lt;artifactId&gt;</span>xstream<span class="nt">&lt;/artifactId&gt;</span>
<span class="nt">&lt;version&gt;</span>1.3.1<span class="nt">&lt;/version&gt;</span>
<span class="nt">&lt;/dependency&gt;</span>
</code></pre></div></div>
<h2 id="configuration-reference">Configuration reference</h2>
<p>Add a <em>constant</em> element to your struts config file to change the value of a configuration setting, like:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nt">&lt;constant</span> <span class="na">name=</span><span class="s">"struts.oval.validateJPAAnnotations"</span> <span class="na">value=</span><span class="s">"true"</span> <span class="nt">/&gt;</span>
</code></pre></div></div>
<table>
<thead>
<tr>
<th>Name</th>
<th>Default Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>struts.oval.validateJPAAnnotations</td>
<td>false</td>
<td>Enables <a href="http://oval.sourceforge.net/userguide.html#d0e242">mapping of JPA annotations to Oval validators</a></td>
</tr>
</tbody>
</table>
<h2 id="resources">Resources</h2>
<ul>
<li>
<p><a href="http://oval.sourceforge.net/userguide.html">OVal User Guide</a></p>
</li>
<li>
<p><a href="http://oval.sourceforge.net/userguide.html">OVal Javadoc</a></p>
</li>
<li>
<p><a href="http://oval.sourceforge.net/userguide.html#d0e1138">OVal Tutorials</a></p>
</li>
</ul>
</section>
</article>
<footer class="container">
<div class="col-md-12">
Copyright &copy; 2000-2018 <a href="http://www.apache.org/">The Apache Software Foundation </a>.
All Rights Reserved.
</div>
<div class="col-md-12">
Apache Struts, Struts, Apache, the Apache feather logo, and the Apache Struts project logos are
trademarks of The Apache Software Foundation.
</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>