Permalink
Browse files

Merge branch '2.0.x' of github.com:grails/grails-doc

Conflicts:
	build.gradle
  • Loading branch information...
2 parents ead119a + 0bce7a6 commit ca300650b9e8276364ead50e0377b31bd6d50b90 @pledbrook committed May 2, 2012
View
4 README.md
@@ -39,6 +39,10 @@ Again, this can save a significant amount of time and memory.
The main English user guide is generated in the `build/docs` directory, with the `guide` sub-directory containing the user guide part and the `ref` folder containing the reference material. To view the user guide, simply open `build/docs/index.html`.
+If you want to disable building of translations, you can use:
+
+ ./gradlew -Den.only=true docs
+
Contributing Documentation
--------------------------
View
22 build.gradle
@@ -1,22 +1,22 @@
apply plugin: "base"
-version = System.getProperty("grails.version") ?: "2.0.0-1"
+version = System.getProperty("grails.version") ?: "2.0.2"
archivesBaseName = "grails-docs"
-checkOutDir = "${buildDir.path}/checkout"
-outputDir = "${buildDir.path}/docs"
+ext.checkOutDir = "${buildDir.path}/checkout"
+ext.outputDir = "${buildDir.path}/docs"
-explicitGrailsHome = System.getProperty("grails.home")
-grailsHome = explicitGrailsHome ? file(explicitGrailsHome).absolutePath : "$checkOutDir/grails-src"
+ext.explicitGrailsHome = System.getProperty("grails.home")
+ext.grailsHome = explicitGrailsHome ? file(explicitGrailsHome).absolutePath : "$checkOutDir/grails-src"
configurations {
publish
}
buildscript {
repositories {
- mavenRepo urls: "http://repo.grails.org/grails/core"
+ mavenRepo url: "http://repo.grails.org/grails/core"
}
dependencies {
@@ -97,9 +97,11 @@ tasks.addRule("Pattern: publishPdf_<lang>") { String taskName ->
task docs(dependsOn: ['publishPdf'])
-for (f in new File(projectDir, "src").listFiles()) {
- if (f.directory && !(f.name in ["en", "guide", "ref"])) {
- docs.dependsOn << "publishPdf_${f.name}"
+if (!System.getProperty("en.only")) {
+ for (f in new File(projectDir, "src").listFiles()) {
+ if (f.directory && !(f.name in ["en", "guide", "ref"])) {
+ docs.dependsOn << "publishPdf_${f.name}"
+ }
}
}
@@ -112,5 +114,5 @@ artifacts {
}
task wrapper(type: Wrapper) {
- gradleVersion = '1.0-milestone-4'
+ gradleVersion = '1.0-milestone-9'
}
View
2 buildSrc/build.gradle
@@ -1,7 +1,7 @@
apply plugin: "groovy"
repositories {
- mavenRepo urls: "http://repo.grails.org/grails/core"
+ mavenRepo url: "http://repo.grails.org/grails/core"
}
dependencies {
View
BIN gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
View
4 gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Thu May 12 10:17:57 BST 2011
+#Tue Apr 03 09:07:42 BST 2012
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=http\://repo.gradle.org/gradle/distributions/gradle-1.0-milestone-4-bin.zip
+distributionUrl=http\://services.gradle.org/distributions/gradle-1.0-milestone-9-bin.zip
View
106 gradlew
@@ -1,16 +1,16 @@
#!/bin/bash
##############################################################################
-## ##
-## Gradle wrapper script for UN*X ##
-## ##
+##
+## Gradle start up script for UN*X
+##
##############################################################################
-# Uncomment those lines to set JVM options. GRADLE_OPTS and JAVA_OPTS can be used together.
-GRADLE_OPTS="$GRADLE_OPTS -Xmx1024m -XX:MaxPermSize=512m"
-JAVA_OPTS="$JAVA_OPTS"
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
-GRADLE_APP_NAME=Gradle
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
@@ -42,54 +42,51 @@ case "`uname`" in
;;
esac
-# Attempt to set JAVA_HOME if it's not already set.
-if [ -z "$JAVA_HOME" ] ; then
- if $darwin ; then
- [ -z "$JAVA_HOME" -a -d "/Library/Java/Home" ] && export JAVA_HOME="/Library/Java/Home"
- [ -z "$JAVA_HOME" -a -d "/System/Library/Frameworks/JavaVM.framework/Home" ] && export JAVA_HOME="/System/Library/Frameworks/JavaVM.framework/Home"
- else
- javaExecutable="`which javac`"
- [ -z "$javaExecutable" -o "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ] && die "JAVA_HOME not set and cannot find javac to deduce location, please set JAVA_HOME."
- # readlink(1) is not available as standard on Solaris 10.
- readLink=`which readlink`
- [ `expr "$readLink" : '\([^ ]*\)'` = "no" ] && die "JAVA_HOME not set and readlink not available, please set JAVA_HOME."
- javaExecutable="`readlink -f \"$javaExecutable\"`"
- javaHome="`dirname \"$javaExecutable\"`"
- javaHome=`expr "$javaHome" : '\(.*\)/bin'`
- export JAVA_HOME="$javaHome"
- fi
-fi
-
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
- [ -n "$JAVACMD" ] && JAVACMD=`cygpath --unix "$JAVACMD"`
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
-STARTER_MAIN_CLASS=org.gradle.wrapper.GradleWrapperMain
-CLASSPATH=`dirname "$0"`/gradle/wrapper/gradle-wrapper.jar
-WRAPPER_PROPERTIES=`dirname "$0"`/gradle/wrapper/gradle-wrapper.properties
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/"
+APP_HOME="`pwd -P`"
+cd "$SAVED"
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
# Determine the Java command to use to start the JVM.
-if [ -z "$JAVACMD" ] ; then
- if [ -n "$JAVA_HOME" ] ; then
- if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
- # IBM's JDK on AIX uses strange locations for the executables
- JAVACMD="$JAVA_HOME/jre/sh/java"
- else
- JAVACMD="$JAVA_HOME/bin/java"
- fi
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
else
- JAVACMD="java"
+ JAVACMD="$JAVA_HOME/bin/java"
fi
-fi
-if [ ! -x "$JAVACMD" ] ; then
- die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
-fi
-if [ -z "$JAVA_HOME" ] ; then
- warn "JAVA_HOME environment variable is not set"
fi
# Increase the maximum file descriptors if we can.
@@ -108,15 +105,14 @@ if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
fi
fi
-# For Darwin, add GRADLE_APP_NAME to the JAVA_OPTS as -Xdock:name
+# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
- JAVA_OPTS="$JAVA_OPTS -Xdock:name=$GRADLE_APP_NAME"
-# we may also want to set -Xdock:image
+ JAVA_OPTS="$JAVA_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
- JAVA_HOME=`cygpath --path --mixed "$JAVA_HOME"`
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
@@ -158,11 +154,11 @@ if $cygwin ; then
esac
fi
-GRADLE_APP_BASE_NAME=`basename "$0"`
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
-exec "$JAVACMD" $JAVA_OPTS $GRADLE_OPTS \
- -classpath "$CLASSPATH" \
- -Dorg.gradle.appname="$GRADLE_APP_BASE_NAME" \
- -Dorg.gradle.wrapper.properties="$WRAPPER_PROPERTIES" \
- $STARTER_MAIN_CLASS \
- "$@"
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
View
52 gradlew.bat
@@ -1,24 +1,37 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
-@rem ##
-@rem Gradle startup script for Windows ##
-@rem ##
+@rem
+@rem Gradle startup script for Windows
+@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
-@rem Uncomment those lines to set JVM options. GRADLE_OPTS and JAVA_OPTS can be used together.
-@rem set GRADLE_OPTS=%GRADLE_OPTS% -Xmx512m
-set JAVA_OPTS=%JAVA_OPTS% -Xmx1024m -XX:MaxPermSize=256m
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.\
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
set JAVA_EXE=java.exe
-if not defined JAVA_HOME goto init
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+goto fail
+
+:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
@@ -29,14 +42,14 @@ echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
-echo.
-goto end
+
+goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
-if "%eval[2+2]" == "4" goto 4NT_args
+if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
@@ -56,27 +69,22 @@ set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
-set STARTER_MAIN_CLASS=org.gradle.wrapper.GradleWrapperMain
-set CLASSPATH=%DIRNAME%\gradle\wrapper\gradle-wrapper.jar
-set WRAPPER_PROPERTIES=%DIRNAME%\gradle\wrapper\gradle-wrapper.properties
-
-set GRADLE_OPTS=%JAVA_OPTS% %GRADLE_OPTS% -Dorg.gradle.wrapper.properties="%WRAPPER_PROPERTIES%"
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
-"%JAVA_EXE%" %GRADLE_OPTS% -classpath "%CLASSPATH%" %STARTER_MAIN_CLASS% %CMD_LINE_ARGS%
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
-if not "%OS%"=="Windows_NT" echo 1 > nul | choice /n /c:1
-
+:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
-if not "" == "%GRADLE_EXIT_CONSOLE%" exit "%ERRORLEVEL%"
-exit /b "%ERRORLEVEL%"
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
-:omega
+:omega
View
1 resources/doc.properties
@@ -89,6 +89,7 @@ api.org.hibernate=http://docs.jboss.org/hibernate/core/3.6/javadocs
api.org.springframework=http://static.springsource.org/spring/docs/3.0.x/javadoc-api
api.javax.servlet=http://download.oracle.com/javaee/1.4/api
api.java.=http://download.oracle.com/javase/1.5.0/docs/api
+api.groovy.lang.=http://groovy.codehaus.org/api
# Regular expression to parse out source code
source.tag.regex=/\s*?def\s+?[a-zA-Z]+?\s*?=\s*?\{\s*?attrs\s*?,{0,1}\s*?body{0,1}\s*?->.+?/
View
2 src/en/guide/GORM/persistenceBasics.gdoc
@@ -1,4 +1,4 @@
-A key thing to remember about Grails is that under the surface Grails is using "Hibernate":http://www.hibernate.org/ for persistence. If you are coming from a background of using "ActiveRecord":http://wiki.rubyonrails.org/rails/pages/ActiveRecord or "iBatis":http://ibatis.apache.org/, Hibernate's "session" model may feel a little strange.
+A key thing to remember about Grails is that under the surface Grails is using "Hibernate":http://www.hibernate.org/ for persistence. If you are coming from a background of using "ActiveRecord":http://wiki.rubyonrails.org/rails/pages/ActiveRecord or [iBatis/MyBatis|http://www.mybatis.org/], Hibernate's "session" model may feel a little strange.
Grails automatically binds a Hibernate session to the currently executing request. This lets you use the [save|domainClasses] and [delete|domainClasses] methods as well as other GORM methods transparently.
View
1 src/en/guide/commandLine/buildCustomising.gdoc
@@ -26,6 +26,7 @@ userHome | The user's home directory.
grailsHome | The location of the Grails installation in use (may be @null@).
grailsVersion | The version of Grails being used by the project.
grailsEnv | The current Grails environment.
+config | The configuration settings defined in the project's @BuildConfig.groovy@ file. Access properties in the same way as you access runtime settings: @grailsSettings.config.foo.bar.hello@.
compileDependencies | A list of compile-time project dependencies as @File@ instances.
testDependencies | A list of test-time project dependencies as @File@ instances.
runtimeDependencies | A list of runtime-time project dependencies as @File@ instances.
View
6 src/en/guide/conf.gdoc
@@ -1,5 +1 @@
-It may seem odd that in a framework that embraces "convention-over-configuration" that we tackle this topic now, but since what configuration there is typically a one-off, it is best to get it out the way.
-
-With Grails' default settings you can actually develop an application without doing any configuration whatsoever. Grails ships with an embedded servlet container and in-memory H2 database, so there isn't even a database to set up.
-
-However, typically you should configure a more robust database at some point and that is described in the following section.
+It may seem odd that in a framework that embraces "convention-over-configuration" that we tackle this topic now. With Grails' default settings you can actually develop an application without doing any configuration whatsoever, as the quick start demonstrates, but it's important to learn where and how to override the conventions when you need to. Later sections of the user guide will mention what configuration settings you can use, but not how to set them. The assumption is that you have at least read the first section of this chapter!
View
109 src/en/guide/conf/config.gdoc
@@ -1,49 +1,120 @@
-For general configuration Grails provides a file called @grails-app/conf/Config.groovy@. This file uses Groovy's "ConfigSlurper":http://groovy.codehaus.org/ConfigSlurper which is very similar to Java properties files except it is pure Groovy hence you can reuse variables and use proper Java types!
+For general configuration Grails provides two files:
-You can add your own configuration in here, for example:
+* @grails-app/conf/BuildConfig.groovy@
+* @grails-app/conf/Config.groovy@
+
+Both of them use Groovy's "ConfigSlurper":http://groovy.codehaus.org/ConfigSlurper syntax. The first, @BuildConfig.groovy@, is for settings that are used when running Grails commands, such as @compile@, @doc@, etc. The second file, @Config.groovy@, is for settings that are used when your application is running. This means that @Config.groovy@ is packaged with your application, but @BuildConfig.groovy@ is not. Don't worry if you're not clear on the distinction: the guide will tell you which file to put a particular setting in.
+
+The most basic syntax is similar to that of Java properties files with dot notation on the left-hand side:
{code}
foo.bar.hello = "world"
{code}
-Then later in your application you can access these settings in one of two ways. The most common is from the [GrailsApplication|api:org.codehaus.groovy.grails.commons.GrailsApplication] object, which is available as a variable in controllers and tag libraries:
+Note that the value is a Groovy string literal! Those quotes around 'world' are important. In fact, this highlights one of the advantages of the ConfigSlurper syntax over properties files: the property values can be any valid Groovy type, such as strings, integers, or arbitrary objects!
+
+Things become more interesting when you have multiple settings with the same base. For example, you could have the two settings
{code}
-class MyController {
- def hello() {
- def recipient = grailsApplication.config.foo.bar.hello
+foo.bar.hello = "world"
+foo.bar.good = "bye"
+{code}
- render "Hello ${recipient}"
+both of which have the same base: @foo.bar@. The above syntax works but it's quite repetitive and verbose. You can remove some of that verbosity by nesting properties at the dots:
+
+{code}
+foo {
+ bar {
+ hello = "world"
+ good = "bye"
}
}
{code}
-The other way involves getting a reference to the [ConfigurationHolder|api:org.codehaus.groovy.grails.commons.ConfigurationHolder] class that holds a reference to the configuration object:
+or by only partially nesting them:
{code}
-import org.codehaus.groovy.grails.commons.*
-...
-def config = ConfigurationHolder.config
-assert "world" == config.foo.bar.hello
+foo {
+ bar.hello = "world"
+ bar.good = "bye"
+}
{code}
-{warning}
-ConfigurationHolder and ApplicationHolder are deprecated and will be removed in a future version of Grails, so it is highly preferable to access the @GrailsApplication@ and config from the @grailsApplication@ variable.
-{warning}
+However, you can't nest after using the dot notation. In other words, this *won't* work:
+
+{code}
+// Won't work!
+foo.bar {
+ hello = "world"
+ good = "bye"
+}
+{code}
-Within @Config.groovy@ you can access several variables:
+Within both @BuildConfig.groovy@ and @Config.groovy@ you can access several implicit variables from configuration values:
{table}
*Variable* | *Description*
userHome | Location of the home directory for the account that is running the Grails application.
+grailsHome | Location of the home directory for the account that is running the Grails application.
appName | The application name as it appears in application.properties.
appVersion | The application version as it appears in application.properties.
-grailsApplication | The @GrailsApplication@ instance.
{table}
-So if you want to include the application name and version in a mail footer for example, you could do it like this:
+For example:
{code}
-mail.footer = "Sent from \${appName} \${appVersion}"
+my.tmp.dir = "\${userHome}/.grails/tmp"
+{code}
+
+In addition, @BuildConfig.groovy@ has
+
+{table}
+*Variable* | *Description*
+grailsVersion | The version of Grails used to build the project.
+grailsSettings | An object containing various build related settings, such as @baseDir@. It's of type [@BuildSettings@|api:grails.util.BuildSettings].
+{table}
+
+and @Config.groovy@ has
+
+{table}
+*Variable* | *Description*
+grailsApplication | The [@GrailsApplication@|api:org.codehaus.groovy.grails.commons.GrailsApplication] instance.
+{table}
+
+Those are the basics of adding settings to the configuration file, but how do you access those settings from your own application? That depends on which config you want to read.
+
+The settings in @BuildConfig.groovy@ are only available from [command scripts|guide:creatingGantScripts] and can be accessed via the @grailsSettings.config@ property like so:
+
+{code}
+target(default: "Example command") {
+ def maxIterations = grailsSettings.config.myapp.iterations.max
+ ...
+}
+{code}
+
+If you want to read runtime configuration settings, i.e. those defined in @Config.groovy@, use the [@grailsApplication@|api:org.codehaus.groovy.grails.commons.GrailsApplication] object, which is available as a variable in controllers and tag libraries:
+
+{code}
+class MyController {
+ def hello() {
+ def recipient = grailsApplication.config.foo.bar.hello
+
+ render "Hello ${recipient}"
+ }
+}
+{code}
+
+and can be easily injected into services and other Grails artifacts:
+
+{code}
+class MyService {
+ def grailsApplication
+
+ String greeting() {
+ def recipient = grailsApplication.config.foo.bar.hello
+ return "Hello ${recipient}"
+ }
+}
{code}
+As you can see, when accessing configuration settings you use the same dot notation as when you define them.
View
37 src/en/guide/conf/config/builtInOptions.gdoc
@@ -1,13 +1,34 @@
-Grails also provides the following configuration options:
+Grails has a set of core settings that are worth knowing about. Their defaults are suitable for most projects, but it's important to understand what they do because you may need one or more of them later.
-* @grails.config.locations@ - The location of properties files or addition Grails Config files that should be merged with main configuration
-* @grails.enable.native2ascii@ - Set this to false if you do not require native2ascii conversion of Grails i18n properties files
+h3. Build settings
+
+Let's start with some important build settings. Although Grails requires JDK 6 when developing your applications, it is possible to deploy those applications to JDK 5 containers. Simply set the following in @BuildConfig.groovy@:
+
+{code}
+grails.project.source.level = "1.5"
+grails.project.target.level = "1.5"
+{code}
+
+Note that source and target levels are different to the standard public version of JDKs, so JDK 5 -> 1.5, JDK 6 -> 1.6, and JDK 7 -> 1.7.
+
+In addition, Grails supports Servlet versions 2.5 and above but defaults to 2.5. If you wish to use newer features of the Servlet API (such as 3.0 async support) you should configure the @grails.servlet.version@ setting appropriately:
+
+{code}
+grails.servlet.version = "3.0"
+{code}
+
+h3. Runtime settings
+
+On the runtime front, i.e. @Config.groovy@, there are quite a few more core settings:
+
+* @grails.config.locations@ - The location of properties files or addition Grails Config files that should be merged with main configuration. See the [section on externalised config|guide:configExternalized].
+* @grails.enable.native2ascii@ - Set this to false if you do not require native2ascii conversion of Grails i18n properties files (default: true).
* @grails.views.default.codec@ - Sets the default encoding regime for GSPs - can be one of 'none', 'html', or 'base64' (default: 'none'). To reduce risk of XSS attacks, set this to 'html'.
-* @grails.views.gsp.encoding@ - The file encoding used for GSP source files (default is 'utf-8')
-* @grails.mime.file.extensions@ - Whether to use the file extension to dictate the mime type in [Content Negotiation|guide:contentNegotiation]
-* @grails.mime.types@ - A map of supported mime types used for [Content Negotiation|guide:contentNegotiation]
-* @grails.serverURL@ - A string specifying the server URL portion of absolute links, including server name e.g. grails.serverURL="http://my.yourportal.com". See [createLink|Tags].
-* @grails.views.gsp.sitemesh.preprocess@ - Whether SiteMesh parses the output coming from GSP for the head, meta, title and body tags.
+* @grails.views.gsp.encoding@ - The file encoding used for GSP source files (default: 'utf-8').
+* @grails.mime.file.extensions@ - Whether to use the file extension to dictate the mime type in [Content Negotiation|guide:contentNegotiation] (default: true).
+* @grails.mime.types@ - A map of supported mime types used for [Content Negotiation|guide:contentNegotiation].
+* @grails.serverURL@ - A string specifying the server URL portion of absolute links, including server name e.g. grails.serverURL="http://my.yourportal.com". See [createLink|Tags]. Also used by redirects.
+* @grails.views.gsp.sitemesh.preprocess@ - Determines whether SiteMesh preprocessing happens. Disabling this slows down page rendering, but if you need SiteMesh to parse the generated HTML from a GSP view then disabling it is the right option. Don't worry if you don't understand this advanced property: leave it set to true.
h3. War generation
View
2 src/en/guide/conf/config/logging.gdoc
@@ -51,7 +51,7 @@ There are two main ways to get hold of a logger:
# use the @log@ instance injected into artifacts such as domain classes, controllers and services;
# use the Commons Logging API directly.
-If you use the dynamic @log@ property, then the name of the logger is 'grails.app.<type>.<className>', where @type@ is the type of the artifact, for example 'controller' or 'service, and @className@ is the fully qualified name of the artifact. For example, if you have this service:
+If you use the dynamic @log@ property, then the name of the logger is 'grails.app.<type>.<className>', where @type@ is the type of the artifact, for example 'controllers' or 'services', and @className@ is the fully qualified name of the artifact. For example, if you have this service:
{code:java}
package org.example
View
8 src/en/guide/gettingStarted/ide.gdoc
@@ -2,7 +2,13 @@ h4. IntelliJ IDEA
[IntelliJ IDEA|http://www.jetbrains.com/idea] offer good support for Groovy and Grails developers. Refer to the section on [Groovy and Grails|http://www.jetbrains.com/idea/features/groovy_grails.html] support on the JetBrains website for a feature overview.
-To integrate Grails with IntelliJ run the following command to generate appropriate project files:
+IntelliJ IDEA comes in two flavours; the open source "Community Edition" and the commercial "Ultimate Edition".
+Both offers support for Groovy, but only Ultimate Edition offers Grails support.
+
+With Ultimate Edition, there is no need to use the @grails integrate-with --intellij@ command, as Ultimate Edition understands Grails projects natively. Just open the project with @File -> New Project -> Create project from existing sources@.
+
+You can still use Community Edition for Grails development, but you will miss out on all the Grails specific features like automatic classpath management, GSP editor and quick access to Grails commands.
+To integrate Grails with Community Edition run the following command to generate appropriate project files:
{code}
grails integrate-with --intellij
View
24 src/en/guide/gettingStarted/requirements.gdoc
@@ -1,20 +1,16 @@
-Before installing Grails you will as a minimum need a Java Development Kit (JDK) installed version 1.6 or above and environment variable called @JAVA_HOME@ pointing to the location of this installation. On some platforms (for example OS X) the Java installation is automatically detected. However in many cases you will want to manually configure the location of Java. For example:
+Before installing Grails you will need as a minimum a Java Development Kit (JDK) installed version 1.6 or above. Download the appropriate JDK for your operating system, run the installer, and then set up an environment variable called @JAVA_HOME@ pointing to the location of this installation. If you're unsure how to do this, we recommend the video installation guides from [grailsexample.net|http://www.grailsexample.net/]:
-{code}
-export JAVA_HOME=/Library/Java/Home
-export PATH="$PATH:$JAVA_HOME/bin"
-{code}
+* [Windows|http://www.grailsexample.net/installing-a-grails-development-environment-on-windows/]
+* [Linux|http://www.grailsexample.net/installing-a-grails-development-environment-on-linux/]
+* [Mac OS X|http://www.grailsexample.net/installing-a-grails-development-environment-on-os-x/]
-Note that although JDK 1.6 is required to use Grails at development time it is possible to deploy Grails to JDK 1.5 VMs by setting the @grails.project.source.level@ and @grails.project.target.level@ settings to "1.5" in @grails-app/conf/BuildConfig.groovy@:
+These will show you how to install Grails too, not just the JDK.
-{code}
-grails.project.source.level = 1.5
-grails.project.target.level = 1.5
-{code}
+On some platforms (for example OS X) the Java installation is automatically detected. However in many cases you will want to manually configure the location of Java. For example:
-In addition, Grails supports Servlet versions 2.5 and above. If you wish to use newer features of the Servlet API (such as 3.0) you should configure the @grails.servlet.version@ in @BuildConfig.groovy@ appropriately:
-
-{code}
-grails.servlet.version = "3.0"
{code}
+export JAVA_HOME=/Library/Java/Home
+export PATH="$PATH:$JAVA_HOME/bin"
+{code}
+if you're using bash or another variant of the Bourne Shell.
View
2 src/en/guide/i18n.gdoc
@@ -4,4 +4,4 @@ Grails supports Internationalization (i18n) out of the box by leveraging the und
A Locale object represents a specific geographical, political, or cultural region. An operation that requires a Locale to perform its task is called locale-sensitive and uses the Locale to tailor information for the user. For example, displaying a number is a locale-sensitive operation--the number should be formatted according to the customs/conventions of the user's native country, region, or culture.
{quote}
-A Locale is made up of a [language code|http://www.loc.gov/standards/iso639-2/englangn.html] and a [country code|http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html]. For example "en_US" is the code for US english, whilst "en_GB" is the for British English.
+A Locale is made up of a [language code|http://www.loc.gov/standards/iso639-2/php/English_list.php] and a [country code|http://www.iso.org/iso/country_codes/iso_3166_code_lists/country_names_and_code_elements.htm]. For example "en_US" is the code for US english, whilst "en_GB" is the code for British English.
View
8 src/en/guide/plugins/addingDynamicMethodsAtRuntime.gdoc
@@ -2,7 +2,7 @@ h4. The Basics
Grails plugins let you register dynamic methods with any Grails-managed or other class at runtime. This work is done in a @doWithDynamicMethods@ closure.
-For Grails-managed classes like controllers, tag libraries and so forth you can add methods, constructors etc. using the "ExpandoMetaClass":http://groovy.codehaus.org/ExpandoMetaClass mechanism by accessing each controller's [MetaClass|api:http://groovy.codehaus.org/api/groovy/lang/MetaObjectProtocol.html]:
+For Grails-managed classes like controllers, tag libraries and so forth you can add methods, constructors etc. using the "ExpandoMetaClass":http://groovy.codehaus.org/ExpandoMetaClass mechanism by accessing each controller's [MetaClass|api:groovy.lang.MetaClass]:
{code:java}
class ExamplePlugin {
@@ -57,7 +57,8 @@ class ExampleHibernatePlugin {
}
}
}
-}{code}
+}
+{code}
Also because of the autowiring and dependency injection capability of the Spring container you can implement more powerful dynamic constructors that use the application context to wire dependencies into your object at runtime:
@@ -71,6 +72,7 @@ class MyConstructorPlugin {
}
}
}
-}{code}
+}
+{code}
Here we actually replace the default constructor with one that looks up prototyped Spring beans instead!
View
2 src/en/guide/plugins/hookingIntoBuildEvents.gdoc
@@ -15,6 +15,8 @@ ant.copy(file: "${pluginBasedir}/src/samples/SamplePluginConfig.groovy",
todir: "${basedir}/grails-app/conf")
{code}
+The @pluginBasedir@ variable is not available in custom scripts, but you can use @fooPluginDir@, where @foo@ is the name of your plugin.
+
h4. Scripting events
It is also possible to hook into command line scripting events. These are events triggered during execution of Grails target and plugin scripts.
View
24 src/en/guide/spring/propertyPlaceholderConfiguration.gdoc
@@ -1,6 +1,6 @@
Grails supports the notion of property placeholder configuration through an extended version of Spring's [PropertyPlaceholderConfigurer|api:org.springframework.beans.factory.config.PropertyPlaceholderConfigurer], which is typically useful in combination with [externalized configuration|guide:configExternalized].
-Settings defined in either "ConfigSlurper":http://groovy.codehaus.org/ConfigSlurper scripts or Java properties files can be used as placeholder values for Spring configuration in @grails-app/conf/spring/resources.xml@. For example given the following entries in @grails-app/conf/Config.groovy@ (or an externalized config):
+Settings defined in either "ConfigSlurper":http://groovy.codehaus.org/ConfigSlurper scripts or Java properties files can be used as placeholder values for Spring configuration in @grails-app/conf/spring/resources.xml@ and @grails-app/conf/spring/resources.groovy@. For example given the following entries in @grails-app/conf/Config.groovy@ (or an externalized config):
{code:java}
database.driver="com.mysql.jdbc.Driver"
@@ -20,3 +20,25 @@ You can then specify placeholders in @resources.xml@ as follows using the famili
</property>
</bean>
{code}
+
+To specify placeholders in @resources.groovy@ you need to use single quotes:
+
+{code:java}
+dataSource(org.springframework.jdbc.datasource.DriverManagerDataSource) {
+ driverClassName = '${database.driver}'
+ url = 'jdbc:${database.dbname}'
+}
+{code}
+
+This sets the property value to a literal string which is later resolved against the config by Spring's PropertyPlaceholderConfigurer.
+
+A better option for @resources.groovy@ is to access properties through the @grailsApplication@ variable:
+
+{code:java}
+dataSource(org.springframework.jdbc.datasource.DriverManagerDataSource) {
+ driverClassName = grailsApplication.config.database.driver
+ url = "jdbc\:${grailsApplication.config.database.dbname}"
+}
+{code}
+
+Using this approach will keep the types as defined in your config.
View
5 src/en/guide/testing/unitTesting/unitTestingTagLibraries.gdoc
@@ -31,6 +31,10 @@ class SimpleTagLib {
def hello = { attrs, body ->
out << "Hello ${attrs.name ?: 'World'}"
}
+
+ def bye = { attrs, body ->
+ out << "Bye ${attrs.author.name ?: 'World'}"
+ }
}
{code}
@@ -42,6 +46,7 @@ class SimpleTagLibTests {
void testHelloTag() {
assert applyTemplate('<s:hello />') == 'Hello World'
assert applyTemplate('<s:hello name="Fred" />') == 'Hello Fred'
+ assert applyTemplate('<s:bye author="${author}" />', [author: new Author(name: 'Fred')]) == 'Bye Fred'
}
}
{code}
View
4 src/en/guide/theWebLayer/controllers/dataBinding.gdoc
@@ -31,6 +31,10 @@ def save() {
This has the same effect as using the implicit constructor.
+{warning}
+These forms of data binding in Grails are very convenient, but also indiscriminate. In other words, they will bind _all_ non-transient, typed instance properties of the target object, including ones that you may not want bound. Just because the form in your UI doesn't submit all the properties, an attacker can still send malign data via a raw HTTP request. Fortunately, Grails also makes it easy to protect against such attacks - see the section titled "Data Binding and Security concerns" for more information.
+{warning}
+
h4. Data binding and Single-ended Associations
If you have a @one-to-one@ or @many-to-one@ association you can use Grails' data binding capability to update these relationships too. For example if you have an incoming request such as:
View
3 src/en/guide/toc.yml
@@ -214,9 +214,10 @@ validation:
title: Validation
constraints: Declaring Constraints
validatingConstraints: Validating Constraints
+ sharingConstraints: Sharing Constraints Between Classes
validationOnTheClient: Validation on the Client
validationAndInternationalization: Validation and Internationalization
- validationNonDomainAndCommandObjectClasses: Validation Non Domain and Command Object Classes
+ validationNonDomainAndCommandObjectClasses: Applying Validation to Other Classes
services:
title: The Service Layer
declarativeTransactions:
View
90 src/en/guide/validation/sharingConstraints.gdoc
@@ -0,0 +1,90 @@
+A common pattern in Grails is to use [command objects|guide:commandObjects] 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.
+
+h3. Global Constraints
+
+In addition to defining constraints in domain classes, command objects and [other validateable classes|guide:validationNonDomainAndCommandObjectClasses], you can also define them in @grails-app/conf/Config.groovy@:
+
+{code}
+grails.gorm.default.constraints = {
+ '*'(nullable: true, size: 1..20)
+ myShared(nullable: false, blank: false)
+}
+{code}
+
+These constraints are not attached to any particular classes, but they can be easily referenced from any validateable class:
+
+{code:java}
+class User {
+ ...
+
+ static constraints = {
+ login shared: "myShared"
+ }
+}
+{code}
+
+Note the use of the @shared@ argument, whose value is the name of one of the constraints defined in @grails.gorm.default.constraints@. Despite the name of the configuration setting, you can reference these shared constraints from any validateable class, such as command objects.
+
+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.
+
+h3. Importing Constraints
+
+Grails 2 introduced an alternative approach to sharing constraints that allows you to import a set of constraints from one class into another.
+
+Let's say you have a domain class like so:
+
+{code}
+class User {
+ String firstName
+ String lastName
+ String passwordHash
+
+ static constraints = {
+ firstName blank: false, nullable: false
+ lastName blank: false, nullable: false
+ passwordHash blank: false, nullable: false
+ }
+}
+{code}
+
+You then want to create a command object, @UserCommand@, that shares some of the properties of the domain class and the corresponding constraints. You do this with the @importFrom()@ method:
+
+{code}
+class UserCommand {
+ String firstName
+ String lastName
+ String password
+ String confirmPassword
+
+ static constraints = {
+ importFrom User
+
+ password blank: false, nullable: false
+ confirmPassword blank: false, nullable: false
+ }
+}
+{code}
+
+This will import all the constraints from the @User@ domain class and apply them to @UserCommand@. The import will ignore any constraints in the source class (@User@) that don't have corresponding properties in the importing class (@UserCommand@). In the above example, only the 'firstName' and 'lastName' constraints will be imported into @UserCommand@ because those are the only properties shared by the two classes.
+
+If you want more control over which constraints are imported, use the @include@ and @exclude@ 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:
+
+{code}
+...
+static constraints = {
+ importFrom User, include: ["lastName"]
+ ...
+}
+{code}
+
+or if you wanted all constraints that ended with 'Name':
+
+{code}
+...
+static constraints = {
+ importFrom User, include: [/.*Name/]
+ ...
+}
+{code}
+
+Of course, @exclude@ does the reverse, specifying which constraints should _not_ be imported.
View
68 src/en/ref/Constraints.gdoc
@@ -17,7 +17,7 @@ class User {
Refer to the user guide topic on [Constraints|guide:constraints] for more information.
-h1. Global Constraints
+h2. Global Constraints
You can apply constraints globally inside @grails-app/conf/Config.groovy@ as follows:
@@ -47,7 +47,69 @@ class User {
}
{code}
-h1. Quick reference
+h2. Sharing Constraints
+
+Global constraints are one way of sharing constraints between different classes, for example between a domain class and a command object. This is no longer the only way. Grails 2 introduces a new syntax for the @constraints@ block that allows you to reuse constraints directly from another class.
+
+Let's say you have a domain class like so:
+
+{code}
+class User {
+ String firstName
+ String lastName
+ String passwordHash
+
+ static constraints = {
+ firstName blank: false, nullable: false
+ lastName blank: false, nullable: false
+ passwordHash blank: false, nullable: false
+ }
+}
+{code}
+
+You then want to create a command object, @UserCommand@, that shares some of the properties of the domain class and the corresponding constraints. You do this with the @importFrom()@ method:
+
+{code}
+class UserCommand {
+ String firstName
+ String lastName
+ String password
+ String confirmPassword
+
+ static constraints = {
+ importFrom User
+
+ password blank: false, nullable: false
+ confirmPassword blank: false, nullable: false
+ }
+}
+{code}
+
+This will import all the constraints from the @User@ domain class and apply them to @UserCommand@. The import will ignore any constraints in the source class (@User@) that don't have corresponding properties in the importing class (@UserCommand@). In the above case, only the 'firstName' and 'lastName' constraints will be imported into @UserCommand@.
+
+If you want more control over which constraints are imported, use the @include@ and @exclude@ named 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:
+
+{code}
+...
+static constraints = {
+ importFrom User, include: ["lastName"]
+ ...
+}
+{code}
+
+or if you wanted all constraints that ended with 'Name':
+
+{code}
+...
+static constraints = {
+ importFrom User, include: [/.*Name/]
+ ...
+}
+{code}
+
+Of course, @exclude@ does the reverse, specifying which constraints should _not_ be imported.
+
+h2. Quick Reference
{table}
Constraint | Description | Example
@@ -70,7 +132,7 @@ url | Validates that a String value is a valid URL. | @homePage(url: true)@
validator | Adds custom validation to a field. | See documentation
{table}
-h1. Scaffolding
+h2. Scaffolding
Some constraints have no impact on persistence but customize the scaffolding. It's not usually good practice to include UI information in your domain, but it's a great convenience if you use Grails' scaffolding extensively.
View
31 src/en/ref/Tags/isAvailable.gdoc
@@ -0,0 +1,31 @@
+h1. isAvailable
+
+h2. Purpose
+
+Renders its body if and only if a named plugin is installed in the current project. Note that it uses the 'plugin' namespace.
+
+h2. Examples
+
+{code:xml}
+<plugin:isAvailable name="spring-security-core">
+You have Spring Security installed!
+</plugin:isAvailable>
+
+<plugin:isAvailable name="resources" version="1.2">
+ <%-- Do something that requires version 1.2 of Resources plugin --%>
+</plugin:isAvailable>
+{code}
+
+h2. Description
+
+Sometimes you want to only display something in a view if a plugin is installed, particularly if you're developing another plugin and you can't know whether another plugin is installed or not. For example, your plugin may provide a tag cloud and you want it to integrate with, but not require, the Taggable plugin. In that case, you can use this tag to selectively include code or markup in your views, partial templates, etc.
+
+Attributes
+
+* @name@ - the name of the plugin you're testing for.
+* @version@ (optional) - the version of the plugin that you're testing for. This doesn't support version ranges, so be careful using it.
+
+h2. Source
+
+{source:tag=PluginTagLib.isAvailable}
+{source}
View
31 src/en/ref/Tags/isNotAvailable.gdoc
@@ -0,0 +1,31 @@
+h1. isNotAvailable
+
+h2. Purpose
+
+Renders its body if and only if a named plugin is _not_ installed in the current project. Note that it uses the 'plugin' namespace.
+
+h2. Examples
+
+{code:xml}
+<plugin:isNotAvailable name="spring-security-core">
+You don't have Spring Security installed!
+</plugin:isNotAvailable>
+
+<plugin:isNotAvailable name="resources" version="1.2">
+ <%-- Do something unless version 1.2 of Resources plugin is installed --%>
+</plugin:isNotAvailable>
+{code}
+
+h2. Description
+
+Sometimes you want to only display something in a view if a plugin is not installed, particularly if you're developing another plugin and you can't know whether another plugin is installed or not. For example, your plugin may provide a tag cloud and you want it to integrate with, but not require, the Taggable plugin. In that case, you can use this tag to provide default code or markup in your views, partial templates, etc. that is used if Taggable isn't installed.
+
+Attributes
+
+* @name@ - the name of the plugin you're testing for.
+* @version@ (optional) - the version of the plugin that you're testing for. This doesn't support version ranges, so be careful using it.
+
+h2. Source
+
+{source:tag=PluginTagLib.isNotAvailable}
+{source}

0 comments on commit ca30065

Please sign in to comment.