| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" |
| "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
| <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> |
| <head> |
| <!-- Matomo --> |
| <script> |
| var _paq = window._paq = window._paq || []; |
| /* tracker methods like "setCustomDimension" should be called before "trackPageView" */ |
| _paq.push(["setDoNotTrack", true]); |
| _paq.push(["disableCookies"]); |
| _paq.push(['trackPageView']); |
| _paq.push(['enableLinkTracking']); |
| (function() { |
| var u="https://analytics.apache.org/"; |
| _paq.push(['setTrackerUrl', u+'matomo.php']); |
| _paq.push(['setSiteId', '79']); |
| 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 --> |
| <title>12 Validation 5.3.0</title> |
| <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> |
| <link rel="stylesheet" href="../css/main.css" type="text/css" media="screen, print" title="Style" charset="utf-8"/> |
| <link rel="stylesheet" href="../css/pdf.css" type="text/css" media="print" title="PDF" charset="utf-8"/> |
| <script type="text/javascript"> |
| function addJsClass() { |
| var classes = document.body.className.split(" "); |
| classes.push("js"); |
| document.body.className = classes.join(" "); |
| } |
| </script> |
| </head> |
| |
| <body class="body" onload="addJsClass();"> |
| <div id="navigation"> |
| <div class="navTitle"> |
| |
| The Grails Framework |
| </div> |
| <div class="navLinks"> |
| <ul> |
| <li> |
| <div id="nav-summary" onmouseover="toggleNavSummary(false)" onmouseout="toggleNavSummary(true)"> |
| <a href="../guide/index.html" class="button">Table of contents</a> |
| |
| <div id="nav-summary-childs" style="display:none;"> |
| |
| <div class="toc-item" style="margin-left:0"><a href="../guide/introduction.html"><strong>1</strong><span>Introduction</span></a> |
| </div> |
| |
| <div class="toc-item" style="margin-left:0"><a href="../guide/gettingStarted.html"><strong>2</strong><span>Getting Started</span></a> |
| </div> |
| |
| <div class="toc-item" style="margin-left:0"><a href="../guide/upgrading.html"><strong>3</strong><span>Upgrading from the previous versions</span></a> |
| </div> |
| |
| <div class="toc-item" style="margin-left:0"><a href="../guide/conf.html"><strong>4</strong><span>Configuration</span></a> |
| </div> |
| |
| <div class="toc-item" style="margin-left:0"><a href="../guide/commandLine.html"><strong>5</strong><span>The Command Line</span></a> |
| </div> |
| |
| <div class="toc-item" style="margin-left:0"><a href="../guide/profiles.html"><strong>6</strong><span>Application Profiles</span></a> |
| </div> |
| |
| <div class="toc-item" style="margin-left:0"><a href="../guide/GORM.html"><strong>7</strong><span>Object Relational Mapping (GORM)</span></a> |
| </div> |
| |
| <div class="toc-item" style="margin-left:0"><a href="../guide/theWebLayer.html"><strong>8</strong><span>The Web Layer</span></a> |
| </div> |
| |
| <div class="toc-item" style="margin-left:0"><a href="../guide/traits.html"><strong>9</strong><span>Traits</span></a> |
| </div> |
| |
| <div class="toc-item" style="margin-left:0"><a href="../guide/REST.html"><strong>10</strong><span>REST</span></a> |
| </div> |
| |
| <div class="toc-item" style="margin-left:0"><a href="../guide/async.html"><strong>11</strong><span>Asynchronous Programming</span></a> |
| </div> |
| |
| <div class="toc-item" style="margin-left:0"><a href="../guide/validation.html"><strong>12</strong><span>Validation</span></a> |
| </div> |
| |
| <div class="toc-item" style="margin-left:0"><a href="../guide/services.html"><strong>13</strong><span>The Service Layer</span></a> |
| </div> |
| |
| <div class="toc-item" style="margin-left:0"><a href="../guide/staticTypeCheckingAndCompilation.html"><strong>14</strong><span>Static Type Checking And Compilation</span></a> |
| </div> |
| |
| <div class="toc-item" style="margin-left:0"><a href="../guide/testing.html"><strong>15</strong><span>Testing</span></a> |
| </div> |
| |
| <div class="toc-item" style="margin-left:0"><a href="../guide/i18n.html"><strong>16</strong><span>Internationalization</span></a> |
| </div> |
| |
| <div class="toc-item" style="margin-left:0"><a href="../guide/security.html"><strong>17</strong><span>Security</span></a> |
| </div> |
| |
| <div class="toc-item" style="margin-left:0"><a href="../guide/plugins.html"><strong>18</strong><span>Plugins</span></a> |
| </div> |
| |
| <div class="toc-item" style="margin-left:0"><a href="../guide/spring.html"><strong>19</strong><span>Grails and Spring</span></a> |
| </div> |
| |
| <div class="toc-item" style="margin-left:0"><a href="../guide/scaffolding.html"><strong>20</strong><span>Scaffolding</span></a> |
| </div> |
| |
| <div class="toc-item" style="margin-left:0"><a href="../guide/deployment.html"><strong>21</strong><span>Deployment</span></a> |
| </div> |
| |
| <div class="toc-item" style="margin-left:0"><a href="../guide/contributing.html"><strong>22</strong><span>Contributing to Grails</span></a> |
| </div> |
| |
| </div> |
| </div> |
| </li> |
| <li class="separator selected"> |
| <a id="ref-button" onclick="localToggle(); return false;" href="#">Quick Reference</a> |
| </li> |
| </ul> |
| </div> |
| |
| |
| </div> |
| |
| <table id="colset" border="0" cellpadding="0" cellspacing="0"> |
| <tr> |
| <td id="col1"> |
| <div id="main" class="corner-all"> |
| |
| |
| <div class="toc-item prev-left"><a href="../guide/async.html"><< <strong>11</strong><span>Asynchronous Programming</span></a></div> |
| |
| |
| <span id='toggle-col1' class="toggle">(<a href="#" onclick="localToggle(); return false;">Quick Reference</a>)</span> |
| |
| |
| <div class="toc-item next-right"><a href="../guide/services.html"><strong>13</strong><span>The Service Layer</span> >></a></div> |
| |
| |
| |
| <div class="project"> |
| <h1>12 Validation</h1> |
| |
| <p><strong>Version:</strong> 5.3.0</p> |
| </div> |
| |
| |
| <div id="table-of-content"> |
| <h2>Table of Contents</h2> |
| |
| <div class="toc-item" style="margin-left:0px"><a href="#constraints"><strong>12.1</strong><span>Declaring Constraints</span></a> |
| </div> |
| |
| <div class="toc-item" style="margin-left:0px"><a href="#validatingConstraints"><strong>12.2</strong><span>Validating Constraints</span></a> |
| </div> |
| |
| <div class="toc-item" style="margin-left:0px"><a href="#sharingConstraints"><strong>12.3</strong><span>Sharing Constraints Between Classes</span></a> |
| </div> |
| |
| <div class="toc-item" style="margin-left:0px"><a href="#validationOnTheClient"><strong>12.4</strong><span>Validation on the Client</span></a> |
| </div> |
| |
| <div class="toc-item" style="margin-left:0px"><a href="#validationAndInternationalization"><strong>12.5</strong><span>Validation and Internationalization</span></a> |
| </div> |
| |
| <div class="toc-item" style="margin-left:0px"><a href="#validationNonDomainAndCommandObjectClasses"><strong>12.6</strong><span>Applying Validation to Other Classes</span></a> |
| </div> |
| |
| </div> |
| |
| |
| |
| <a name="10. Validation"><!-- Legacy link --></a> |
| <h1 id="validation">12 Validation</h1> |
| |
| <div class='contribute-btn'> |
| <button type='button' class='btn btn-default' onclick='window.location.href="https://github.com/grails/grails-doc/edit/5.3.x/src/en/guide/validation.adoc"'> |
| <i class='fa fa-pencil-square-o'></i> Improve this doc |
| </button> |
| </div> |
| |
| |
| <div class="paragraph"> |
| <p>Grails validation capability is built on <a href="https://docs.spring.io/spring/docs/5.3.8/javadoc-api/org/springframework/validation/package-summary.html">Spring’s Validator API</a> and data binding capabilities. However Grails takes this further and provides a unified way to define validation "constraints" with its constraints mechanism.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Constraints in Grails are a way to declaratively specify validation rules. Most commonly they are applied to <a href="GORM.html">domain classes</a>, however <a href="theWebLayer.html#urlmappings">URL Mappings</a> and <a href="theWebLayer.html#commandObjects">Command Objects</a> also support constraints.</p> |
| </div> |
| |
| <a name="10.1 Declaring Constraints"><!-- Legacy link --></a> |
| <h2 id="constraints">12.1 Declaring Constraints</h2> |
| |
| <div class='contribute-btn'> |
| <button type='button' class='btn btn-default' onclick='window.location.href="https://github.com/grails/grails-doc/edit/5.3.x/src/en/guide/validation/constraints.adoc"'> |
| <i class='fa fa-pencil-square-o'></i> Improve this doc |
| </button> |
| </div> |
| |
| |
| <div class="paragraph"> |
| <p>Within a domain class <a href="../ref/Domain%20Classes/constraints.html">constraints</a> are defined with the constraints property that is assigned a code block:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="groovy"><span class="type">class</span> <span class="class">User</span> { |
| <span class="predefined-type">String</span> login |
| <span class="predefined-type">String</span> password |
| <span class="predefined-type">String</span> email |
| <span class="predefined-type">Integer</span> age |
| |
| <span class="directive">static</span> constraints = { |
| ... |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>You then use method calls that match the property name for which the constraint applies in combination with named parameters to specify constraints:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="groovy"><span class="type">class</span> <span class="class">User</span> { |
| ... |
| |
| static constraints = { |
| login <span class="key">size</span>: <span class="integer">5</span>..<span class="integer">15</span>, <span class="key">blank</span>: <span class="predefined-constant">false</span>, <span class="key">unique</span>: <span class="predefined-constant">true</span> |
| password <span class="key">size</span>: <span class="integer">5</span>..<span class="integer">15</span>, <span class="key">blank</span>: <span class="predefined-constant">false</span> |
| email <span class="key">email</span>: <span class="predefined-constant">true</span>, <span class="key">blank</span>: <span class="predefined-constant">false</span> |
| age <span class="key">min</span>: <span class="integer">18</span> |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>In this example we’ve declared that the <code>login</code> property must be between 5 and 15 characters long, it cannot be blank and must be unique. We’ve also applied other constraints to the <code>password</code>, <code>email</code> and <code>age</code> properties.</p> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| By default, all domain class properties are not nullable (i.e. they have an implicit <code>nullable: false</code> constraint). |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p>A complete reference for the available constraints can be found in the Quick Reference section under the Constraints heading.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Note that constraints are only evaluated once which may be relevant for a constraint that relies on a value like an instance of <code>java.util.Date</code>.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="groovy"><span class="type">class</span> <span class="class">User</span> { |
| ... |
| |
| static constraints = { |
| <span class="comment">// this Date object is created when the constraints are evaluated, not</span> |
| <span class="comment">// each time an instance of the User class is validated.</span> |
| birthDate <span class="key">max</span>: <span class="keyword">new</span> <span class="predefined-type">Date</span>() |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_a_word_of_warning_referencing_domain_class_properties_from_constraints">A word of warning - referencing domain class properties from constraints</h3> |
| <div class="paragraph"> |
| <p>It’s very easy to attempt to reference instance variables from the static constraints block, but this isn’t legal in Groovy (or Java). If you do so, you will get a <code>MissingPropertyException</code> for your trouble. For example, you may try</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="groovy"><span class="type">class</span> <span class="class">Response</span> { |
| Survey survey |
| Answer answer |
| |
| <span class="directive">static</span> constraints = { |
| survey <span class="key">blank</span>: <span class="predefined-constant">false</span> |
| answer <span class="key">blank</span>: <span class="predefined-constant">false</span>, <span class="key">inList</span>: survey.answers |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>See how the <code>inList</code> constraint references the instance property <code>survey</code>? That won’t work. Instead, use a custom <a href="../ref/Constraints/validator.html">validator</a>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="groovy"><span class="type">class</span> <span class="class">Response</span> { |
| ... |
| static constraints = { |
| survey <span class="key">blank</span>: <span class="predefined-constant">false</span> |
| answer <span class="key">blank</span>: <span class="predefined-constant">false</span>, <span class="key">validator</span>: { val, obj -> val <span class="keyword">in</span> obj.survey.answers } |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>In this example, the <code>obj</code> argument to the custom validator is the domain <em>instance</em> that is being validated, so we can access its <code>survey</code> property and return a boolean to indicate whether the new value for the <code>answer</code> property, <code>val</code>, is valid.</p> |
| </div> |
| </div> |
| |
| <a name="10.2 Validating Constraints"><!-- Legacy link --></a> |
| <h2 id="validatingConstraints">12.2 Validating Constraints</h2> |
| |
| <div class='contribute-btn'> |
| <button type='button' class='btn btn-default' onclick='window.location.href="https://github.com/grails/grails-doc/edit/5.3.x/src/en/guide/validation/validatingConstraints.adoc"'> |
| <i class='fa fa-pencil-square-o'></i> Improve this doc |
| </button> |
| </div> |
| |
| |
| <div class="sect3"> |
| <h4 id="_validation_basics">Validation Basics</h4> |
| <div class="paragraph"> |
| <p>Call the <a href="../ref/Domain%20Classes/validate.html">validate</a> method to validate a domain class instance:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="groovy"><span class="keyword">def</span> user = <span class="keyword">new</span> User(params) |
| |
| <span class="keyword">if</span> (user.validate()) { |
| <span class="comment">// do something with user</span> |
| } |
| <span class="keyword">else</span> { |
| user.errors.allErrors.each { |
| println <span class="local-variable">it</span> |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The <code>errors</code> property on domain classes is an instance of the Spring <a href="https://docs.spring.io/spring/docs/5.3.8/javadoc-api/org/springframework/validation/Errors.html">Errors</a> interface. The <code>Errors</code> interface provides methods to navigate the validation errors and also retrieve the original values.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_validation_phases">Validation Phases</h4> |
| <div class="paragraph"> |
| <p>Within Grails there are two phases of validation, the first one being <a href="theWebLayer.html#dataBinding">data binding</a> which occurs when you bind request parameters onto an instance such as:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="groovy"><span class="keyword">def</span> user = <span class="keyword">new</span> User(params)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>At this point you may already have errors in the <code>errors</code> property due to type conversion (such as converting Strings to Dates). You can check these and obtain the original input value using the <code>Errors</code> API:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="groovy"><span class="keyword">if</span> (user.hasErrors()) { |
| <span class="keyword">if</span> (user.errors.hasFieldErrors(<span class="string"><span class="delimiter">"</span><span class="content">login</span><span class="delimiter">"</span></span>)) { |
| println user.errors.getFieldError(<span class="string"><span class="delimiter">"</span><span class="content">login</span><span class="delimiter">"</span></span>).rejectedValue |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The second phase of validation happens when you call <a href="../ref/Domain%20Classes/validate.html">validate</a> or <a href="../ref/Domain%20Classes/save.html">save</a>. This is when Grails will validate the bound values against the <a href="../ref/Domain%20Classes/constraints.html">constraints</a> you defined. For example, by default the <a href="../ref/Domain%20Classes/save.html">save</a> method calls <code>validate</code> before executing, allowing you to write code like:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="groovy"><span class="keyword">if</span> (user.save()) { |
| <span class="keyword">return</span> user |
| } |
| <span class="keyword">else</span> { |
| user.errors.allErrors.each { |
| println <span class="local-variable">it</span> |
| } |
| }</code></pre> |
| </div> |
| </div> |
| </div> |
| |
| |
| <h2 id="sharingConstraints">12.3 Sharing Constraints Between Classes</h2> |
| |
| <div class='contribute-btn'> |
| <button type='button' class='btn btn-default' onclick='window.location.href="https://github.com/grails/grails-doc/edit/5.3.x/src/en/guide/validation/sharingConstraints.adoc"'> |
| <i class='fa fa-pencil-square-o'></i> Improve this doc |
| </button> |
| </div> |
| |
| |
| <div class="paragraph"> |
| <p>A common pattern in Grails is to use <a href="theWebLayer.html#commandObjects">Command Objects</a> for validating user-submitted data and then copy the properties of the command object to the relevant domain classes. This often means that your command objects and domain classes share properties and their constraints. You could manually copy and paste the constraints between the two, but that’s a very error-prone approach. Instead, make use of Grails' global constraints and import mechanism.</p> |
| </div> |
| <div class="sect2"> |
| <h3 id="_global_constraints">Global Constraints</h3> |
| <div class="paragraph"> |
| <p>In addition to defining constraints in domain classes, command objects and <a href="#validationNonDomainAndCommandObjectClasses">other validateable classes</a>, you can also define them in <code>grails-app/conf/runtime.groovy</code>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="groovy">grails.gorm.default.constraints = { |
| <span class="string"><span class="delimiter">'</span><span class="content">*</span><span class="delimiter">'</span></span>(<span class="key">nullable</span>: <span class="predefined-constant">true</span>, <span class="key">size</span>: <span class="integer">1</span>..<span class="integer">20</span>) |
| myShared(<span class="key">nullable</span>: <span class="predefined-constant">false</span>, <span class="key">blank</span>: <span class="predefined-constant">false</span>) |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>These constraints are not attached to any particular classes, but they can be easily referenced from any validateable class:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="groovy"><span class="type">class</span> <span class="class">User</span> { |
| ... |
| |
| static constraints = { |
| login <span class="key">shared</span>: <span class="string"><span class="delimiter">"</span><span class="content">myShared</span><span class="delimiter">"</span></span> |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Note the use of the <code>shared</code> argument, whose value is the name of one of the constraints defined in <code>grails.gorm.default.constraints</code>. Despite the name of the configuration setting, you can reference these shared constraints from any validateable class, such as command objects.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The '*' constraint is a special case: it means that the associated constraints ('nullable' and 'size' in the above example) will be applied to all properties in all validateable classes. These defaults can be overridden by the constraints declared in a validateable class.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="_importing_constraints">Importing Constraints</h3> |
| <div class="paragraph"> |
| <p>Grails 2 introduced an alternative approach to sharing constraints that allows you to import a set of constraints from one class into another.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Let’s say you have a domain class like so:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="groovy"><span class="type">class</span> <span class="class">User</span> { |
| <span class="predefined-type">String</span> firstName |
| <span class="predefined-type">String</span> lastName |
| <span class="predefined-type">String</span> passwordHash |
| |
| <span class="directive">static</span> constraints = { |
| firstName <span class="key">blank</span>: <span class="predefined-constant">false</span>, <span class="key">nullable</span>: <span class="predefined-constant">false</span> |
| lastName <span class="key">blank</span>: <span class="predefined-constant">false</span>, <span class="key">nullable</span>: <span class="predefined-constant">false</span> |
| passwordHash <span class="key">blank</span>: <span class="predefined-constant">false</span>, <span class="key">nullable</span>: <span class="predefined-constant">false</span> |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>You then want to create a command object, <code>UserCommand</code>, that shares some of the properties of the domain class and the corresponding constraints. You do this with the <code>importFrom()</code> method:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="groovy"><span class="type">class</span> <span class="class">UserCommand</span> { |
| <span class="predefined-type">String</span> firstName |
| <span class="predefined-type">String</span> lastName |
| <span class="predefined-type">String</span> password |
| <span class="predefined-type">String</span> confirmPassword |
| |
| <span class="directive">static</span> constraints = { |
| importFrom User |
| |
| password <span class="key">blank</span>: <span class="predefined-constant">false</span>, <span class="key">nullable</span>: <span class="predefined-constant">false</span> |
| confirmPassword <span class="key">blank</span>: <span class="predefined-constant">false</span>, <span class="key">nullable</span>: <span class="predefined-constant">false</span> |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This will import all the constraints from the <code>User</code> domain class and apply them to <code>UserCommand</code>. The import will ignore any constraints in the source class (<code>User</code>) that don’t have corresponding properties in the importing class (<code>UserCommand</code>). In the above example, only the 'firstName' and 'lastName' constraints will be imported into <code>UserCommand</code> because those are the only properties shared by the two classes.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If you want more control over which constraints are imported, use the <code>include</code> and <code>exclude</code> arguments. Both of these accept a list of simple or regular expression strings that are matched against the property names in the source constraints. So for example, if you only wanted to import the 'lastName' constraint you would use:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="groovy">... |
| static constraints = { |
| importFrom User, <span class="key">include</span>: [<span class="string"><span class="delimiter">"</span><span class="content">lastName</span><span class="delimiter">"</span></span>] |
| ... |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>or if you wanted all constraints that ended with 'Name':</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="groovy">... |
| static constraints = { |
| importFrom User, <span class="key">include</span>: [<span class="regexp"><span class="delimiter">/</span><span class="content">.*Name</span><span class="delimiter">/</span></span>] |
| ... |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Of course, <code>exclude</code> does the reverse, specifying which constraints should <em>not</em> be imported.</p> |
| </div> |
| </div> |
| |
| <a name="10.3 Validation on the Client"><!-- Legacy link --></a> |
| <h2 id="validationOnTheClient">12.4 Validation on the Client</h2> |
| |
| <div class='contribute-btn'> |
| <button type='button' class='btn btn-default' onclick='window.location.href="https://github.com/grails/grails-doc/edit/5.3.x/src/en/guide/validation/validationOnTheClient.adoc"'> |
| <i class='fa fa-pencil-square-o'></i> Improve this doc |
| </button> |
| </div> |
| |
| |
| <div class="sect3"> |
| <h4 id="_displaying_errors">Displaying Errors</h4> |
| <div class="paragraph"> |
| <p>Typically if you get a validation error you redirect back to the view for rendering. Once there you need some way of displaying errors. Grails supports a rich set of tags for dealing with errors. To render the errors as a list you can use <a href="https://gsp.grails.org/5.0.0.RC1/ref/Tags/renderErrors.html">renderErrors</a>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="xml"><span class="tag"><g:renderErrors</span> <span class="attribute-name">bean</span>=<span class="string"><span class="delimiter">"</span><span class="content">${user}</span><span class="delimiter">"</span></span> <span class="tag">/></span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>If you need more control you can use <a href="https://gsp.grails.org/5.0.0.RC1/ref/Tags/hasErrors.html">hasErrors</a> and <a href="https://gsp.grails.org/5.0.0.RC1/ref/Tags/eachError.html">eachError</a>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="xml"><span class="tag"><g:hasErrors</span> <span class="attribute-name">bean</span>=<span class="string"><span class="delimiter">"</span><span class="content">${user}</span><span class="delimiter">"</span></span><span class="tag">></span> |
| <span class="tag"><ul></span> |
| <span class="tag"><g:eachError</span> <span class="attribute-name">var</span>=<span class="string"><span class="delimiter">"</span><span class="content">err</span><span class="delimiter">"</span></span> <span class="attribute-name">bean</span>=<span class="string"><span class="delimiter">"</span><span class="content">${user}</span><span class="delimiter">"</span></span><span class="tag">></span> |
| <span class="tag"><li></span>${err}<span class="tag"></li></span> |
| <span class="tag"></g:eachError></span> |
| <span class="tag"></ul></span> |
| <span class="tag"></g:hasErrors></span></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_highlighting_errors">Highlighting Errors</h4> |
| <div class="paragraph"> |
| <p>It is often useful to highlight using a red box or some indicator when a field has been incorrectly input. This can also be done with the <a href="https://gsp.grails.org/5.0.0.RC1/ref/Tags/hasErrors.html">hasErrors</a> by invoking it as a method. For example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="xml"><span class="tag"><div</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">'</span><span class="content">value ${hasErrors(bean:user,field:</span><span class="delimiter">'</span></span><span class="attribute-name">login</span><span class="error">'</span><span class="error">,</span><span class="error">'</span><span class="attribute-name">errors</span><span class="error">'</span><span class="error">)</span><span class="error">}</span><span class="error">'</span><span class="tag">></span> |
| <span class="tag"><input</span> <span class="attribute-name">type</span>=<span class="string"><span class="delimiter">"</span><span class="content">text</span><span class="delimiter">"</span></span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">"</span><span class="content">login</span><span class="delimiter">"</span></span> <span class="attribute-name">value</span>=<span class="string"><span class="delimiter">"</span><span class="content">${fieldValue(bean:user,field:'login')}</span><span class="delimiter">"</span></span><span class="tag">/></span> |
| <span class="tag"></div></span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This code checks if the <code>login</code> field of the <code>user</code> bean has any errors and if so it adds an <code>errors</code> CSS class to the <code>div</code>, allowing you to use CSS rules to highlight the <code>div</code>.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_retrieving_input_values">Retrieving Input Values</h4> |
| <div class="paragraph"> |
| <p>Each error is actually an instance of the <a href="https://docs.spring.io/spring/docs/5.3.8/javadoc-api/org/springframework/validation/FieldError.html">FieldError</a> class in Spring, which retains the original input value within it. This is useful as you can use the error object to restore the value input by the user using the <a href="../ref/Tags/fieldValue.html">fieldValue</a> tag:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="xml"><span class="tag"><input</span> <span class="attribute-name">type</span>=<span class="string"><span class="delimiter">"</span><span class="content">text</span><span class="delimiter">"</span></span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">"</span><span class="content">login</span><span class="delimiter">"</span></span> <span class="attribute-name">value</span>=<span class="string"><span class="delimiter">"</span><span class="content">${fieldValue(bean:user,field:'login')}</span><span class="delimiter">"</span></span><span class="tag">/></span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This code will check for an existing <code>FieldError</code> in the <code>User</code> bean and if there is obtain the originally input value for the <code>login</code> field.</p> |
| </div> |
| </div> |
| |
| <a name="10.4 Validation and Internationalization"><!-- Legacy link --></a> |
| <h2 id="validationAndInternationalization">12.5 Validation and Internationalization</h2> |
| |
| <div class='contribute-btn'> |
| <button type='button' class='btn btn-default' onclick='window.location.href="https://github.com/grails/grails-doc/edit/5.3.x/src/en/guide/validation/validationAndInternationalization.adoc"'> |
| <i class='fa fa-pencil-square-o'></i> Improve this doc |
| </button> |
| </div> |
| |
| |
| <div class="paragraph"> |
| <p>Another important thing to note about errors in Grails is that error messages are not hard coded anywhere. The <a href="https://docs.spring.io/spring/docs/5.3.8/javadoc-api/org/springframework/validation/FieldError.html">FieldError</a> class in Spring resolves messages from message bundles using Grails' <a href="i18n.html">i18n</a> support.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="_constraints_and_message_codes">Constraints and Message Codes</h4> |
| <div class="paragraph"> |
| <p>The codes themselves are dictated by a convention. For example consider the constraints we looked at earlier:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="groovy"><span class="keyword">package</span> com.mycompany.myapp |
| |
| <span class="type">class</span> <span class="class">User</span> { |
| ... |
| |
| static constraints = { |
| login <span class="key">size</span>: <span class="integer">5</span>..<span class="integer">15</span>, <span class="key">blank</span>: <span class="predefined-constant">false</span>, <span class="key">unique</span>: <span class="predefined-constant">true</span> |
| password <span class="key">size</span>: <span class="integer">5</span>..<span class="integer">15</span>, <span class="key">blank</span>: <span class="predefined-constant">false</span> |
| email <span class="key">email</span>: <span class="predefined-constant">true</span>, <span class="key">blank</span>: <span class="predefined-constant">false</span> |
| age <span class="key">min</span>: <span class="integer">18</span> |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>If a constraint is violated, Grails looks by convention for a message code:</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Constraint</th> |
| <th class="tableblock halign-left valign-top">Error Code</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../ref/Constraints/blank.html">blank</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>className.propertyName.blank</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../ref/Constraints/creditCard.html">creditCard</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>className.propertyName.creditCard.invalid</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../ref/Constraints/email.html">email</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>className.propertyName.email.invalid</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../ref/Constraints/inList.html">inList</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>className.propertyName.not.inList</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../ref/Constraints/matches.html">matches</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>className.propertyName.matches.invalid</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../ref/Constraints/max.html">max</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>className.propertyName.max.exceeded</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../ref/Constraints/maxSize.html">maxSize</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>className.propertyName.maxSize.exceeded</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../ref/Constraints/min.html">min</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>className.propertyName.min.notmet</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../ref/Constraints/minSize.html">minSize</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>className.propertyName.minSize.notmet</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../ref/Constraints/notEqual.html">notEqual</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>className.propertyName.notEqual</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../ref/Constraints/nullable.html">nullable</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>className.propertyName.nullable</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../ref/Constraints/range.html">range</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>className.propertyName.range.toosmall</code> or <code>className.propertyName.range.toobig</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../ref/Constraints/size.html">size</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>className.propertyName.size.toosmall</code> or <code>className.propertyName.size.toobig</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../ref/Constraints/unique.html">unique</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>className.propertyName.unique</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../ref/Constraints/url.html">url</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>className.propertyName.url.invalid</code></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="../ref/Constraints/validator.html">validator</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>classname.propertyName.</code> + String returned by Closure</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>In the case of the <code>blank</code> constraint this would be <code>user.login.blank</code> so you would need a message such as the following in your <code>grails-app/i18n/messages.properties</code> file:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="groovy">user.login.blank=Your login name must be specified!</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The class name is looked for both with and without a package, with the packaged version taking precedence. So for example, <code>com.mycompany.myapp.User.login.blank</code> will be used before <code>user.login.blank</code>. This allows for cases where your domain class message codes clash with a plugin’s.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For a reference on what codes are for which constraints refer to the reference guide for each constraint (e.g. <a href="../ref/Constraints/blank.html">blank</a>).</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_displaying_messages">Displaying Messages</h4> |
| <div class="paragraph"> |
| <p>The <a href="https://gsp.grails.org/5.0.0.RC1/ref/Tags/renderErrors.html">renderErrors</a> tag will automatically look up messages for you using the <a href="https://gsp.grails.org/5.0.0.RC1/ref/Tags/message.html">message</a> tag. If you need more control of rendering you can handle this yourself:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="xml"><span class="tag"><g:hasErrors</span> <span class="attribute-name">bean</span>=<span class="string"><span class="delimiter">"</span><span class="content">${user}</span><span class="delimiter">"</span></span><span class="tag">></span> |
| <span class="tag"><ul></span> |
| <span class="tag"><g:eachError</span> <span class="attribute-name">var</span>=<span class="string"><span class="delimiter">"</span><span class="content">err</span><span class="delimiter">"</span></span> <span class="attribute-name">bean</span>=<span class="string"><span class="delimiter">"</span><span class="content">${user}</span><span class="delimiter">"</span></span><span class="tag">></span> |
| <span class="tag"><li></span><span class="tag"><g:message</span> <span class="attribute-name">error</span>=<span class="string"><span class="delimiter">"</span><span class="content">${err}</span><span class="delimiter">"</span></span> <span class="tag">/></span><span class="tag"></li></span> |
| <span class="tag"></g:eachError></span> |
| <span class="tag"></ul></span> |
| <span class="tag"></g:hasErrors></span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>In this example within the body of the <a href="https://gsp.grails.org/5.0.0.RC1/ref/Tags/eachError.html">eachError</a> tag we use the <a href="https://gsp.grails.org/5.0.0.RC1/ref/Tags/message.html">message</a> tag in combination with its <code>error</code> argument to read the message for the given error.</p> |
| </div> |
| </div> |
| |
| <a name="10.5 Validation Non Domain and Command Object Classes"><!-- Legacy link --></a> |
| <h2 id="validationNonDomainAndCommandObjectClasses">12.6 Applying Validation to Other Classes</h2> |
| |
| <div class='contribute-btn'> |
| <button type='button' class='btn btn-default' onclick='window.location.href="https://github.com/grails/grails-doc/edit/5.3.x/src/en/guide/validation/validationNonDomainAndCommandObjectClasses.adoc"'> |
| <i class='fa fa-pencil-square-o'></i> Improve this doc |
| </button> |
| </div> |
| |
| |
| <div class="paragraph"> |
| <p><a href="GORM.html">Domain classes</a> and <a href="theWebLayer.html#commandObjects">Command Objects</a> support validation by default. Other classes may be made validateable by defining the static <code>constraints</code> property in the class (as described above) and then telling the framework about them. It is important that the application register the validateable classes with the framework. Simply defining the <code>constraints</code> property is not sufficient.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="_the_validateable_trait">The Validateable Trait</h4> |
| <div class="paragraph"> |
| <p>Classes which define the static <code>constraints</code> property and implement the <a href="https://grails.apache.org/docs/5.3.0/api/grails/validation/Validateable.html">Validateable</a> trait will be validateable. Consider this example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="title">src/main/groovy/com/mycompany/myapp/User.groovy</div> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="groovy"><span class="keyword">package</span> com.mycompany.myapp |
| |
| <span class="keyword">import</span> <span class="include">grails.validation.Validateable</span> |
| |
| <span class="type">class</span> <span class="class">User</span> <span class="directive">implements</span> Validateable { |
| ... |
| |
| static constraints = { |
| login <span class="key">size</span>: <span class="integer">5</span>..<span class="integer">15</span>, <span class="key">blank</span>: <span class="predefined-constant">false</span>, <span class="key">unique</span>: <span class="predefined-constant">true</span> |
| password <span class="key">size</span>: <span class="integer">5</span>..<span class="integer">15</span>, <span class="key">blank</span>: <span class="predefined-constant">false</span> |
| email <span class="key">email</span>: <span class="predefined-constant">true</span>, <span class="key">blank</span>: <span class="predefined-constant">false</span> |
| age <span class="key">min</span>: <span class="integer">18</span> |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="_programmatic_access">Programmatic access</h5> |
| <div class="paragraph"> |
| <p>Accessing the constraints on a validateable object is slightly different. You can access a command object’s constraints programmatically in another context by accessing the <code>constraintsMap</code> static property of the class. That property is an instance of <code>Map<String, <a href="https://grails.apache.org/docs/5.3.0/api/grails/validation/ConstrainedProperty.html">ConstrainedProperty</a>></code></p> |
| </div> |
| <div class="paragraph"> |
| <p>In the example above, accessing <code>User.constraintsMap.login.blank</code> would yield <code>false</code>, while |
| <code>User.constraintsMap.login.unique</code> would yield <code>true</code>.</p> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div style="clear:both;margin-top:15px;"></div> |
| |
| <div class="toc-item prev-left"><a href="../guide/async.html"><< <strong>11</strong><span>Asynchronous Programming</span></a></div> |
| |
| <div class="toc-item next-right"><a href="../guide/services.html"><strong>13</strong><span>The Service Layer</span> >></a></div> |
| |
| <div style="clear:both"></div> |
| </div> |
| </td> |
| <td id="col2"> |
| <div class="local clearfix"> |
| <div class="local-title"> |
| <a href="../guide/index.html" target="mainFrame">Quick Reference</a> |
| <span class="toggle">(<a href="#" onclick="localToggle(); return false;">hide</a>)</span> |
| </div> |
| <div class="menu"> |
| |
| <div class="menu-block"><h1 class="menu-title" onclick="toggleRef(this.parentNode.childNodes[1])">Command Line</h1><div class="menu-sub"> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/Usage.html">Usage</a></div> |
| |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/bug-report.html">bug-report</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/clean.html">clean</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/compile.html">compile</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/console.html">console</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/create-app.html">create-app</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/create-command.html">create-command</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/create-controller.html">create-controller</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/create-domain-class.html">create-domain-class</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/create-functional-test.html">create-functional-test</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/create-hibernate-cfg-xml.html">create-hibernate-cfg-xml</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/create-integration-test.html">create-integration-test</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/create-interceptor.html">create-interceptor</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/create-plugin.html">create-plugin</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/create-profile.html">create-profile</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/create-script.html">create-script</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/create-service.html">create-service</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/create-taglib.html">create-taglib</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/create-unit-test.html">create-unit-test</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/dependency-report.html">dependency-report</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/docs.html">docs</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/generate-all.html">generate-all</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/generate-controller.html">generate-controller</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/generate-views.html">generate-views</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/help.html">help</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/install-templates.html">install-templates</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/list-plugins.html">list-plugins</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/list-profiles.html">list-profiles</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/package-plugin.html">package-plugin</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/package.html">package</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/plugin-info.html">plugin-info</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/profile-info.html">profile-info</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/run-app.html">run-app</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/run-command.html">run-command</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/run-script.html">run-script</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/schema-export.html">schema-export</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/shell.html">shell</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/stats.html">stats</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/stop-app.html">stop-app</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/test-app.html">test-app</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Command%20Line/war.html">war</a> |
| </div> |
| |
| </div> |
| </div> |
| |
| <div class="menu-block"><h1 class="menu-title" onclick="toggleRef(this.parentNode.childNodes[1])">Constraints</h1><div class="menu-sub"> |
| |
| <div class="menu-item"><a href="../ref/Constraints/Usage.html">Usage</a></div> |
| |
| |
| <div class="menu-item"><a href="../ref/Constraints/attributes.html">attributes</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Constraints/bindable.html">bindable</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Constraints/blank.html">blank</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Constraints/creditCard.html">creditCard</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Constraints/email.html">email</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Constraints/inList.html">inList</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Constraints/matches.html">matches</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Constraints/max.html">max</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Constraints/maxSize.html">maxSize</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Constraints/min.html">min</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Constraints/minSize.html">minSize</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Constraints/notEqual.html">notEqual</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Constraints/nullable.html">nullable</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Constraints/range.html">range</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Constraints/scale.html">scale</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Constraints/size.html">size</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Constraints/unique.html">unique</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Constraints/url.html">url</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Constraints/validator.html">validator</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Constraints/widget.html">widget</a> |
| </div> |
| |
| </div> |
| </div> |
| |
| <div class="menu-block"><h1 class="menu-title" onclick="toggleRef(this.parentNode.childNodes[1])">Controllers</h1><div class="menu-sub"> |
| |
| <div class="menu-item"><a href="../ref/Controllers/Usage.html">Usage</a></div> |
| |
| |
| <div class="menu-item"><a href="../ref/Controllers/actionName.html">actionName</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Controllers/allowedMethods.html">allowedMethods</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Controllers/bindData.html">bindData</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Controllers/chain.html">chain</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Controllers/controllerName.html">controllerName</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Controllers/defaultAction.html">defaultAction</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Controllers/errors.html">errors</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Controllers/flash.html">flash</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Controllers/forward.html">forward</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Controllers/grailsApplication.html">grailsApplication</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Controllers/hasErrors.html">hasErrors</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Controllers/header.html">header</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Controllers/namespace.html">namespace</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Controllers/params.html">params</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Controllers/redirect.html">redirect</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Controllers/render.html">render</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Controllers/request.html">request</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Controllers/respond.html">respond</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Controllers/response.html">response</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Controllers/responseFormats.html">responseFormats</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Controllers/scope.html">scope</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Controllers/servletContext.html">servletContext</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Controllers/session.html">session</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Controllers/withForm.html">withForm</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Controllers/withFormat.html">withFormat</a> |
| </div> |
| |
| </div> |
| </div> |
| |
| <div class="menu-block"><h1 class="menu-title" onclick="toggleRef(this.parentNode.childNodes[1])">Database Mapping</h1><div class="menu-sub"> |
| |
| <div class="menu-item"><a href="../ref/Database%20Mapping/Usage.html">Usage</a></div> |
| |
| |
| <div class="menu-item"><a href="../ref/Database%20Mapping/autoImport.html">autoImport</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Database%20Mapping/autoTimestamp.html">autoTimestamp</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Database%20Mapping/batchSize.html">batchSize</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Database%20Mapping/cache.html">cache</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Database%20Mapping/cascade.html">cascade</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Database%20Mapping/column.html">column</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Database%20Mapping/comment.html">comment</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Database%20Mapping/discriminator.html">discriminator</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Database%20Mapping/dynamicInsert.html">dynamicInsert</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Database%20Mapping/dynamicUpdate.html">dynamicUpdate</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Database%20Mapping/fetch.html">fetch</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Database%20Mapping/id.html">id</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Database%20Mapping/ignoreNotFound.html">ignoreNotFound</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Database%20Mapping/indexColumn.html">indexColumn</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Database%20Mapping/insertable.html">insertable</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Database%20Mapping/joinTable.html">joinTable</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Database%20Mapping/lazy.html">lazy</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Database%20Mapping/order.html">order</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Database%20Mapping/sort.html">sort</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Database%20Mapping/table.html">table</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Database%20Mapping/type.html">type</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Database%20Mapping/updateable.html">updateable</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Database%20Mapping/version.html">version</a> |
| </div> |
| |
| </div> |
| </div> |
| |
| <div class="menu-block"><h1 class="menu-title" onclick="toggleRef(this.parentNode.childNodes[1])">Domain Classes</h1><div class="menu-sub"> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/Usage.html">Usage</a></div> |
| |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/addTo.html">addTo</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/attach.html">attach</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/belongsTo.html">belongsTo</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/clearErrors.html">clearErrors</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/constraints.html">constraints</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/count.html">count</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/countBy.html">countBy</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/createCriteria.html">createCriteria</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/delete.html">delete</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/discard.html">discard</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/embedded.html">embedded</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/errors.html">errors</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/executeQuery.html">executeQuery</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/executeUpdate.html">executeUpdate</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/exists.html">exists</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/fetchMode.html">fetchMode</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/find.html">find</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/findAll.html">findAll</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/findAllBy.html">findAllBy</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/findAllWhere.html">findAllWhere</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/findBy.html">findBy</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/findOrCreateBy.html">findOrCreateBy</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/findOrCreateWhere.html">findOrCreateWhere</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/findOrSaveBy.html">findOrSaveBy</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/findOrSaveWhere.html">findOrSaveWhere</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/findWhere.html">findWhere</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/first.html">first</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/get.html">get</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/getAll.html">getAll</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/getDirtyPropertyNames.html">getDirtyPropertyNames</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/getPersistentValue.html">getPersistentValue</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/hasErrors.html">hasErrors</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/hasMany.html">hasMany</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/hasOne.html">hasOne</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/ident.html">ident</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/instanceOf.html">instanceOf</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/isAttached.html">isAttached</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/isDirty.html">isDirty</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/last.html">last</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/list.html">list</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/listOrderBy.html">listOrderBy</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/load.html">load</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/lock.html">lock</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/mapWith.html">mapWith</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/mappedBy.html">mappedBy</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/mapping.html">mapping</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/merge.html">merge</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/namedQueries.html">namedQueries</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/properties.html">properties</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/read.html">read</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/refresh.html">refresh</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/removeFrom.html">removeFrom</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/save.html">save</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/transients.html">transients</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/validate.html">validate</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/where.html">where</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/whereAny.html">whereAny</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/withCriteria.html">withCriteria</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/withNewSession.html">withNewSession</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/withSession.html">withSession</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Domain%20Classes/withTransaction.html">withTransaction</a> |
| </div> |
| |
| </div> |
| </div> |
| |
| <div class="menu-block"><h1 class="menu-title" onclick="toggleRef(this.parentNode.childNodes[1])">Plug-ins</h1><div class="menu-sub"> |
| |
| <div class="menu-item"><a href="../ref/Plug-ins/Usage.html">Usage</a></div> |
| |
| |
| <div class="menu-item"><a href="../ref/Plug-ins/URL%20mappings.html">URL mappings</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Plug-ins/codecs.html">codecs</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Plug-ins/controllers.html">controllers</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Plug-ins/core.html">core</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Plug-ins/dataSource.html">dataSource</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Plug-ins/domainClasses.html">domainClasses</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Plug-ins/hibernate.html">hibernate</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Plug-ins/i18n.html">i18n</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Plug-ins/logging.html">logging</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Plug-ins/scaffolding.html">scaffolding</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Plug-ins/services.html">services</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Plug-ins/servlets.html">servlets</a> |
| </div> |
| |
| </div> |
| </div> |
| |
| <div class="menu-block"><h1 class="menu-title" onclick="toggleRef(this.parentNode.childNodes[1])">Services</h1><div class="menu-sub"> |
| |
| <div class="menu-item"><a href="../ref/Services/Usage.html">Usage</a></div> |
| |
| |
| <div class="menu-item"><a href="../ref/Services/scope.html">scope</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Services/transactional.html">transactional</a> |
| </div> |
| |
| </div> |
| </div> |
| |
| <div class="menu-block"><h1 class="menu-title" onclick="toggleRef(this.parentNode.childNodes[1])">Servlet API</h1><div class="menu-sub"> |
| |
| |
| <div class="menu-item"><a href="../ref/Servlet%20API/request.html">request</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Servlet%20API/response.html">response</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Servlet%20API/servletContext.html">servletContext</a> |
| </div> |
| |
| <div class="menu-item"><a href="../ref/Servlet%20API/session.html">session</a> |
| </div> |
| |
| </div> |
| </div> |
| |
| </div> |
| </div> |
| </td> |
| </tr> |
| </table> |
| |
| <div id="footer"> |
| Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically. |
| |
| </div> |
| |
| <script type="text/javascript" src="../js/docs.js"></script> |
| |
| </body> |
| </html> |