Drop the Grails 3 sample as it is incompatible with Framework 5

Closes gh-637
This commit is contained in:
Andy Wilkinson
2019-08-31 07:59:43 +01:00
parent 015468685e
commit d586d9f15b
24 changed files with 0 additions and 1080 deletions

View File

@@ -180,10 +180,6 @@ samples {
dependOn 'spring-restdocs-webtestclient:install'
dependOn 'spring-restdocs-asciidoctor:install'
restNotesGrails {
workingDir "$projectDir/samples/rest-notes-grails"
}
restNotesSpringHateoas {
workingDir "$projectDir/samples/rest-notes-spring-hateoas"
}

View File

@@ -44,11 +44,6 @@ If you want to jump straight in, a number of sample applications are available:
|===
| Sample | Build system | Description
| {samples}/rest-notes-grails[Grails]
| Gradle
| Demonstrates the use of Spring REST docs with https://grails.org[Grails] and
https://github.com/spockframework/spock[Spock].
| {samples}/rest-assured[REST Assured]
| Gradle
| Demonstrates the use of Spring REST Docs with http://rest-assured.io[REST Assured].

View File

@@ -1,10 +0,0 @@
.gradle
build/
classes/
.idea
*.iml
*.ipr
*.iws
.project
.settings
.classpath

View File

@@ -1,93 +0,0 @@
# rest-notes-grails
## Overview
This is a sample project using Grails 3, Spock, and Spring REST docs. For more
information about the Grails framework please see [grails.org](https://grails.org).
Grails is built on top of Spring Boot and Gradle so there are a few different ways to
run this project including:
### Gradle Wrapper (recommended)
The gradle wrapper allows a project to build without having Gradle installed locally. The
executable file will acquire the version of Gradle and other dependencies recommended for
this project. This is especially important since some versions of Gradle may cause
conflicts with this project.
On Unix-like platforms, such as Linux and Mac OS X:
```
$ ./gradlew run
```
On Windows:
```
$ gradlew run
```
*Please note*, if you are including integration tests in Grails, they will not run as
part of the `gradle test` task. Run them via the build task or individually as
`gradle integrationTest`
### Gradle Command Line
Clean the project:
```
$ gradle clean
```
Build the project:
```
$ gradle build
```
Run the project:
```
$ gradle run
```
### Grails Command Line
Grails applications also have a command line feature useful for code generation and
running projects locally. The command line is accessible by typing `grails` in the
terminal at the root of the project. Please ensure you are running the correct version
of Grails as specified in [gradle.properties](gradle.properties)
Similar to `gradle clean`, this task destroys the `build` directory and cached assets.
```
grails> clean
```
The 'test-app' task runs all of the tests for the project.
```
grails> test-app
```
The `run-app` task is used to run the application locally. By default, the project is
run in development mode including automatic reloading and not caching static assets. It
is not suggested to use this in production.
```
grails> run-app
```
### Building and Viewing the Docs
This is an example of the Grails API profile. Therefore, there is no view layer to
return the docs as static assets. The result of running `asciidoctor` or `build` is that
the docs are sent to `/build/asciidoc/`. You can then publish them to a destination of
your choosing using the [gradle github-pages](https://github.com/ajoberstar/gradle-git)
plugin or similar.
To just generate documentation and not run the application use:
```
$ ./gradlew asciidoctor
```

View File

@@ -1,101 +0,0 @@
buildscript {
repositories {
mavenCentral()
maven { url "https://repo.grails.org/grails/core" }
}
dependencies {
classpath "org.grails:grails-gradle-plugin:$grailsVersion"
classpath "org.grails.plugins:hibernate5:6.0.7"
}
}
plugins {
id 'org.asciidoctor.convert' version '1.5.3'
}
version "0.1"
group "com.example"
apply plugin: "war"
apply plugin: "eclipse"
apply plugin: "idea"
apply plugin: "org.grails.grails-web"
ext {
restDocsVersion = "2.0.4.BUILD-SNAPSHOT"
snippetsDir = file('src/docs/generated-snippets')
}
repositories {
mavenLocal()
maven { url 'https://repo.spring.io/libs-snapshot' }
maven { url "https://repo.grails.org/grails/core" }
}
dependencyManagement {
dependencies {
dependency "org.springframework.restdocs:spring-restdocs-core:$restDocsVersion"
dependency "org.springframework.restdocs:spring-restdocs-restassured:$restDocsVersion"
dependency "org.springframework.restdocs:spring-restdocs-asciidoctor:$restDocsVersion"
}
imports {
mavenBom "org.grails:grails-bom:$grailsVersion"
}
applyMavenExclusions false
}
dependencies {
asciidoctor "org.springframework.restdocs:spring-restdocs-asciidoctor"
compile "org.springframework.boot:spring-boot-starter-logging"
compile "org.springframework.boot:spring-boot-autoconfigure"
compile "org.springframework.boot:spring-boot-starter-actuator"
compile "org.springframework.boot:spring-boot-starter-tomcat"
compile "org.grails:grails-core"
compile "org.grails:grails-plugin-url-mappings"
compile "org.grails:grails-plugin-rest"
compile "org.grails:grails-plugin-codecs"
compile "org.grails:grails-plugin-interceptors"
compile "org.grails:grails-plugin-services"
compile "org.grails:grails-plugin-datasource"
compile "org.grails:grails-plugin-databinding"
compile "org.grails.plugins:async"
compile "org.grails:grails-web-boot"
compile "org.grails:grails-logging"
compile "org.grails.plugins:cache"
compile "org.grails.plugins:hibernate5"
compile "org.hibernate:hibernate-core:5.1.2.Final"
compile "org.hibernate:hibernate-ehcache:5.1.2.Final"
compile "org.grails.plugins:views-json"
compile "org.grails.plugins:views-json-templates"
console "org.grails:grails-console"
profile "org.grails.profiles:rest-api"
runtime "com.h2database:h2"
runtime 'org.apache.tomcat:tomcat-jdbc'
testCompile "io.rest-assured:rest-assured:3.0.2"
testCompile "org.grails:grails-test-mixins:3.3.0"
testCompile "org.grails.plugins:geb"
testCompile "org.grails:grails-datastore-rest-client"
testCompile "org.springframework.restdocs:spring-restdocs-restassured"
testRuntime "org.seleniumhq.selenium:selenium-htmlunit-driver:2.47.1"
testRuntime "net.sourceforge.htmlunit:htmlunit:2.18"
}
ext {
snippetsDir = file('build/generated-snippets')
}
test {
outputs.dir snippetsDir
}
asciidoctor {
dependsOn integrationTest
inputs.dir snippetsDir
}
build.dependsOn asciidoctor

View File

@@ -1 +0,0 @@
grailsVersion=3.3.9

View File

@@ -1,5 +0,0 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip

View File

@@ -1,172 +0,0 @@
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# 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\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
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 [ ! -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
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_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
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

View File

@@ -1,84 +0,0 @@
@if "%DEBUG%" == "" @echo off
@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
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@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=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%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
if exist "%JAVA_EXE%" goto init
echo.
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.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%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
: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 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -1,100 +0,0 @@
---
grails:
profile: rest-api
codegen:
defaultPackage: com.example
info:
app:
name: '@info.app.name@'
version: '@info.app.version@'
grailsVersion: '@info.app.grailsVersion@'
spring:
groovy:
template:
check-template-location: false
---
grails:
mime:
disable:
accept:
header:
userAgents:
- Gecko
- WebKit
- Presto
- Trident
types:
all: '*/*'
atom: application/atom+xml
css: text/css
csv: text/csv
form: application/x-www-form-urlencoded
html:
- text/html
- application/xhtml+xml
js: text/javascript
json:
- application/json
- text/json
multipartForm: multipart/form-data
rss: application/rss+xml
text: text/plain
hal:
- application/hal+json
- application/hal+xml
xml:
- text/xml
- application/xml
urlmapping:
cache:
maxsize: 1000
controllers:
defaultScope: singleton
converters:
encoding: UTF-8
hibernate:
cache:
queries: false
---
dataSource:
pooled: true
jmxExport: true
driverClassName: org.h2.Driver
username: sa
password:
environments:
development:
dataSource:
dbCreate: create-drop
url: jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
test:
dataSource:
dbCreate: update
url: jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
server:
port: 0
production:
dataSource:
dbCreate: update
url: jdbc:h2:./prodDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
properties:
jmxEnabled: true
initialSize: 5
maxActive: 50
minIdle: 5
maxIdle: 25
maxWait: 10000
maxAge: 600000
timeBetweenEvictionRunsMillis: 5000
minEvictableIdleTimeMillis: 60000
validationQuery: SELECT 1
validationQueryTimeout: 3
validationInterval: 15000
testOnBorrow: true
testWhileIdle: true
testOnReturn: false
jdbcInterceptors: ConnectionState
defaultTransactionIsolation: 2 # TRANSACTION_READ_COMMITTED

View File

@@ -1,39 +0,0 @@
/*
* Copyright 2014-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import grails.util.BuildSettings
import grails.util.Environment
// See https://logback.qos.ch/manual/groovy.html for details on configuration
appender('STDOUT', ConsoleAppender) {
encoder(PatternLayoutEncoder) {
pattern = "%level %logger - %msg%n"
}
}
root(ERROR, ['STDOUT'])
def targetDir = BuildSettings.TARGET_DIR
if (Environment.isDevelopmentMode() && targetDir) {
appender("FULL_STACKTRACE", FileAppender) {
file = "${targetDir}/stacktrace.log"
append = true
encoder(PatternLayoutEncoder) {
pattern = "%level %logger - %msg%n"
}
}
logger("StackTrace", ERROR, ['FULL_STACKTRACE'], false)
}

View File

@@ -1,2 +0,0 @@
// Place your Spring DSL code here
beans = {}

View File

@@ -1,28 +0,0 @@
/*
* Copyright 2014-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example
class UrlMappings {
static mappings = {
'/notes'(resources: 'note')
"500"(view: '/error')
"404"(view: '/notFound')
}
}

View File

@@ -1,37 +0,0 @@
/*
* Copyright 2014-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example
import grails.rest.Resource
@Resource(uri='/notes')
class Note {
Long id
String title
String body
static hasMany = [tags: Tag]
static mapping = {
tags joinTable: [name: "mm_notes_tags", key: 'mm_note_id' ]
}
}

View File

@@ -1,36 +0,0 @@
/*
* Copyright 2014-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example
import grails.rest.Resource
@Resource(uri='/tags')
class Tag {
Long id
String name
static hasMany = [notes: Note]
static belongsTo = Note
static mapping = {
notes joinTable: [name: "mm_notes_tags", key: 'mm_tag_id']
}
}

View File

@@ -1,56 +0,0 @@
default.doesnt.match.message=Property [{0}] of class [{1}] with value [{2}] does not match the required pattern [{3}]
default.invalid.url.message=Property [{0}] of class [{1}] with value [{2}] is not a valid URL
default.invalid.creditCard.message=Property [{0}] of class [{1}] with value [{2}] is not a valid credit card number
default.invalid.email.message=Property [{0}] of class [{1}] with value [{2}] is not a valid e-mail address
default.invalid.range.message=Property [{0}] of class [{1}] with value [{2}] does not fall within the valid range from [{3}] to [{4}]
default.invalid.size.message=Property [{0}] of class [{1}] with value [{2}] does not fall within the valid size range from [{3}] to [{4}]
default.invalid.max.message=Property [{0}] of class [{1}] with value [{2}] exceeds maximum value [{3}]
default.invalid.min.message=Property [{0}] of class [{1}] with value [{2}] is less than minimum value [{3}]
default.invalid.max.size.message=Property [{0}] of class [{1}] with value [{2}] exceeds the maximum size of [{3}]
default.invalid.min.size.message=Property [{0}] of class [{1}] with value [{2}] is less than the minimum size of [{3}]
default.invalid.validator.message=Property [{0}] of class [{1}] with value [{2}] does not pass custom validation
default.not.inlist.message=Property [{0}] of class [{1}] with value [{2}] is not contained within the list [{3}]
default.blank.message=Property [{0}] of class [{1}] cannot be blank
default.not.equal.message=Property [{0}] of class [{1}] with value [{2}] cannot equal [{3}]
default.null.message=Property [{0}] of class [{1}] cannot be null
default.not.unique.message=Property [{0}] of class [{1}] with value [{2}] must be unique
default.paginate.prev=Previous
default.paginate.next=Next
default.boolean.true=True
default.boolean.false=False
default.date.format=yyyy-MM-dd HH:mm:ss z
default.number.format=0
default.created.message={0} {1} created
default.updated.message={0} {1} updated
default.deleted.message={0} {1} deleted
default.not.deleted.message={0} {1} could not be deleted
default.not.found.message={0} not found with id {1}
default.optimistic.locking.failure=Another user has updated this {0} while you were editing
default.home.label=Home
default.list.label={0} List
default.add.label=Add {0}
default.new.label=New {0}
default.create.label=Create {0}
default.show.label=Show {0}
default.edit.label=Edit {0}
default.button.create.label=Create
default.button.edit.label=Edit
default.button.update.label=Update
default.button.delete.label=Delete
default.button.delete.confirm.message=Are you sure?
# Data binding errors. Use "typeMismatch.$className.$propertyName to customize (eg typeMismatch.Book.author)
typeMismatch.java.net.URL=Property {0} must be a valid URL
typeMismatch.java.net.URI=Property {0} must be a valid URI
typeMismatch.java.util.Date=Property {0} must be a valid Date
typeMismatch.java.lang.Double=Property {0} must be a valid number
typeMismatch.java.lang.Integer=Property {0} must be a valid number
typeMismatch.java.lang.Long=Property {0} must be a valid number
typeMismatch.java.lang.Short=Property {0} must be a valid number
typeMismatch.java.math.BigDecimal=Property {0} must be a valid number
typeMismatch.java.math.BigInteger=Property {0} must be a valid number
typeMismatch=Property {0} is type-mismatched

View File

@@ -1,28 +0,0 @@
/*
* Copyright 2014-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example
import grails.boot.GrailsApp
import grails.boot.config.GrailsAutoConfiguration
class Application extends GrailsAutoConfiguration {
static void main(String[] args) {
GrailsApp.run(Application, args)
}
}

View File

@@ -1,31 +0,0 @@
/*
* Copyright 2014-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example
class BootStrap {
def init = { servletContext ->
environments {
test {
new Note(title: 'Hello, World!', body: 'Hello from the Integration Test').save()
}
}
}
def destroy = {}
}

View File

@@ -1,6 +0,0 @@
response.status 500
json {
message "Internal server error"
error 500
}

View File

@@ -1,6 +0,0 @@
response.status 404
json {
message "Not Found"
error 404
}

View File

@@ -1,98 +0,0 @@
= Grails RESTful Notes API Guide
Andy Wilkinson; Jenn Strater
:doctype: book
:icons: font
:source-highlighter: highlightjs
:toc: left
:toclevels: 4
:sectlinks:
:operation-curl-request-title: Example request
:operation-http-response-title: Example response
[[overview]]
= Overview
[[overview-http-verbs]]
== HTTP verbs
Grails RESTful notes tries to adhere as closely as possible to standard HTTP and REST conventions in its
use of HTTP verbs.
|===
| Verb | Usage
| `GET`
| Used to retrieve a resource
| `POST`
| Used to create a new resource
| `PATCH`
| Used to update an existing resource, including partial updates
| `DELETE`
| Used to delete an existing resource
|===
[[overview-http-status-codes]]
== HTTP status codes
Grails RESTful notes tries to adhere as closely as possible to standard HTTP and REST conventions in its
use of HTTP status codes.
|===
| Status code | Usage
| `200 OK`
| The request completed successfully
| `201 Created`
| A new resource has been created successfully. The resource's URI is available from the response's
`Location` header
| `204 No Content`
| An update to an existing resource has been applied successfully
| `400 Bad Request`
| The request was malformed. The response body will include an error providing further information
| `404 Not Found`
| The requested resource did not exist
|===
[[resources]]
= Resources
[[resources-notes]]
== Notes
The Notes resources is used to create and list notes
[[resources-notes-list]]
=== Listing notes
A `GET` request will list all of the service's notes.
operation::notes-list-example[snippets='response-fields,curl-request,http-response']
[[resources-notes-create]]
=== Creating a note
A `POST` request is used to create a note
operation::notes-create-example[snippets='request-fields,curl-request,http-response']
[[resources-note-retrieve]]
=== Retrieve a note
A `GET` request will retrieve the details of a note
operation::note-get-example[snippets='response-fields,curl-request,http-response']

View File

@@ -1,138 +0,0 @@
/*
* Copyright 2014-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example
import org.springframework.restdocs.payload.JsonFieldType
import static io.restassured.RestAssured.given
import static org.hamcrest.CoreMatchers.is
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse
import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath
import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields
import static org.springframework.restdocs.payload.PayloadDocumentation.subsectionWithPath
import static org.springframework.restdocs.restassured3.operation.preprocess.RestAssuredPreprocessors.modifyUris
import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document
import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.documentationConfiguration
import io.restassured.builder.RequestSpecBuilder
import io.restassured.specification.RequestSpecification
import grails.test.mixin.integration.Integration
import grails.transaction.Rollback
import org.junit.Rule
import org.springframework.beans.factory.annotation.Value
import org.springframework.http.MediaType
import org.springframework.restdocs.JUnitRestDocumentation
import spock.lang.Specification
@Integration
@Rollback
class ApiDocumentationSpec extends Specification {
@Rule
JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation()
@Value('${local.server.port}')
Integer serverPort
protected RequestSpecification documentationSpec
void setup() {
this.documentationSpec = new RequestSpecBuilder()
.addFilter(documentationConfiguration(restDocumentation))
.build()
}
void 'test and document notes list request'() {
expect:
given(this.documentationSpec)
.accept(MediaType.APPLICATION_JSON.toString())
.filter(document('notes-list-example',
preprocessRequest(modifyUris()
.host('api.example.com')
.removePort()),
preprocessResponse(prettyPrint()),
responseFields(
fieldWithPath('[].id').description('the id of the note'),
fieldWithPath('[].title').description('the title of the note'),
fieldWithPath('[].body').description('the body of the note'),
fieldWithPath('[].tags').type(JsonFieldType.ARRAY).description('the list of tags associated with the note'),
)))
.when()
.port(this.serverPort)
.get('/notes')
.then()
.assertThat()
.statusCode(is(200))
}
void 'test and document create new note'() {
expect:
given(this.documentationSpec)
.accept(MediaType.APPLICATION_JSON.toString())
.contentType(MediaType.APPLICATION_JSON.toString())
.filter(document('notes-create-example',
preprocessRequest(modifyUris()
.host('api.example.com')
.removePort()),
preprocessResponse(prettyPrint()),
requestFields(
fieldWithPath('title').description('the title of the note'),
fieldWithPath('body').description('the body of the note'),
subsectionWithPath('tags').type(JsonFieldType.ARRAY).description('a list of tags associated to the note')
),
responseFields(
fieldWithPath('id').description('the id of the note'),
fieldWithPath('title').description('the title of the note'),
fieldWithPath('body').description('the body of the note'),
subsectionWithPath('tags').type(JsonFieldType.ARRAY).description('the list of tags associated with the note')
)))
.body('{ "body": "My test example", "title": "Eureka!", "tags": [{"name": "testing123"}] }')
.when()
.port(this.serverPort)
.post('/notes')
.then()
.assertThat()
.statusCode(is(201))
}
void 'test and document getting specific note'() {
expect:
given(this.documentationSpec)
.accept(MediaType.APPLICATION_JSON.toString())
.filter(document('note-get-example',
preprocessRequest(modifyUris()
.host('api.example.com')
.removePort()),
preprocessResponse(prettyPrint()),
responseFields(
fieldWithPath('id').description('the id of the note'),
fieldWithPath('title').description('the title of the note'),
fieldWithPath('body').description('the body of the note'),
fieldWithPath('tags').type(JsonFieldType.ARRAY).description('the list of tags associated with the note'),
)))
.when()
.port(this.serverPort)
.get('/notes/1')
.then()
.assertThat()
.statusCode(is(200))
}
}