Skip to content

Commit

Permalink
Support Spring REST Docs 3.0.0 (ePages-de#211)
Browse files Browse the repository at this point in the history
According to spring-rest-docs 'requestParameters' are replaced by
'queryParameters' and 'formParameters'.
If 'requestParameters' are used to document the API, this must be replaced
by one of the new functions

Upgrades (needed to use spring-rest-docs 3.0.0):
* gradle 7.6
* kotlin 1.7.10
* spring-boot 3.0.2
* java 17
  • Loading branch information
tobiaskrauss committed Jan 23, 2023

Verified

This commit was signed with the committer’s verified signature.
sunya-ch Sunyanan Choochotkaew
1 parent 9b84729 commit 415f402
Showing 22 changed files with 268 additions and 110 deletions.
8 changes: 4 additions & 4 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ plugins {
id("pl.allegro.tech.build.axion-release") version "1.9.2"
jacoco
java
kotlin("jvm") version "1.4.20" apply false
kotlin("jvm") version "1.7.10" apply false
`maven-publish`
}

@@ -58,12 +58,12 @@ allprojects {
subprojects {

val jacksonVersion by extra { "2.12.2" }
val springBootVersion by extra { "2.1.9.RELEASE" }
val springRestDocsVersion by extra { "2.0.4.RELEASE" }
val springBootVersion by extra { "3.0.2" }
val springRestDocsVersion by extra { "3.0.0" }
val junitVersion by extra { "5.4.2" }

tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "1.8"
kotlinOptions.jvmTarget = "17"
}

tasks.withType<Test> {
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
3 changes: 2 additions & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
18 changes: 14 additions & 4 deletions gradlew
Original file line number Diff line number Diff line change
@@ -55,7 +55,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@@ -80,10 +80,10 @@ do
esac
done

APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit

APP_NAME="Gradle"
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
@@ -143,12 +143,16 @@ fi
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@@ -205,6 +209,12 @@ set -- \
org.gradle.wrapper.GradleWrapperMain \
"$@"

# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi

# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
15 changes: 9 additions & 6 deletions gradlew.bat
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@
@rem limitations under the License.
@rem

@if "%DEBUG%" == "" @echo off
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@@ -25,7 +25,8 @@
if "%OS%"=="Windows_NT" setlocal

set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

@@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome

set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
if %ERRORLEVEL% equ 0 goto execute

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar

:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
if %ERRORLEVEL% equ 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
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%

:mainEnd
if "%OS%"=="Windows_NT" endlocal
1 change: 1 addition & 0 deletions restdocs-api-spec-mockmvc/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@ dependencies {
testImplementation("org.springframework.boot:spring-boot-starter-test:$springBootVersion") {
exclude("junit")
}
testImplementation("org.springframework.boot:spring-boot-starter-validation:$springBootVersion")
testImplementation("org.junit.jupiter:junit-jupiter-engine:$junitVersion")
testImplementation("org.junit-pioneer:junit-pioneer:0.3.0")
testImplementation("org.springframework.boot:spring-boot-starter-hateoas:$springBootVersion")
Original file line number Diff line number Diff line change
@@ -2,16 +2,18 @@ package com.epages.restdocs.apispec

import com.epages.restdocs.apispec.ResourceDocumentation.parameterWithName
import com.epages.restdocs.apispec.ResourceDocumentation.resource
import jakarta.validation.constraints.NotEmpty
import org.hibernate.validator.constraints.Length
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
import org.springframework.context.ConfigurableApplicationContext
import org.springframework.hateoas.EntityModel
import org.springframework.hateoas.IanaLinkRelations
import org.springframework.hateoas.Link
import org.springframework.hateoas.Resource
import org.springframework.hateoas.mvc.BasicLinkBuilder
import org.springframework.hateoas.server.mvc.BasicLinkBuilder.linkToCurrentMapping
import org.springframework.http.HttpHeaders.ACCEPT
import org.springframework.http.HttpHeaders.CONTENT_TYPE
import org.springframework.http.ResponseEntity
@@ -26,7 +28,6 @@ import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestHeader
import org.springframework.web.bind.annotation.RestController
import java.util.UUID
import javax.validation.constraints.NotEmpty

@ExtendWith(SpringExtension::class)
@WebMvcTest
@@ -53,17 +54,17 @@ open class ResourceSnippetIntegrationTest {
@PathVariable otherId: Int?,
@RequestHeader("X-Custom-Header") customHeader: String,
@RequestBody testDataHolder: TestDataHolder
): ResponseEntity<Resource<TestDataHolder>> {
val resource = Resource(testDataHolder.copy(id = UUID.randomUUID().toString()))
val link = BasicLinkBuilder.linkToCurrentMapping().slash("some").slash(someId).slash("other").slash(otherId).toUri().toString()
resource.add(Link(link, Link.REL_SELF))
resource.add(Link(link, "multiple"))
resource.add(Link(link, "multiple"))
): ResponseEntity<EntityModel<TestDataHolder>> {
val resource = EntityModel.of(testDataHolder.copy(id = UUID.randomUUID().toString()))
val link = linkToCurrentMapping().slash("some").slash(someId).slash("other").slash(otherId).toUri().toString()
resource.add(Link.of(link, IanaLinkRelations.SELF))
resource.add(Link.of(link, "multiple"))
resource.add(Link.of(link, "multiple"))

return ResponseEntity
.ok()
.header("X-Custom-Header", customHeader)
.body<Resource<TestDataHolder>>(resource)
.body<EntityModel<TestDataHolder>>(resource)
}
}
}
Original file line number Diff line number Diff line change
@@ -327,6 +327,7 @@ object OpenApi20Generator {
SecurityType.OAUTH2 -> addSecurity(OAUTH2_SECURITY_NAME, securityRequirements2ScopesList(securityRequirements))
SecurityType.BASIC -> addSecurity(BASIC_SECURITY_NAME, null)
SecurityType.API_KEY -> addSecurity(API_KEY_SECURITY_NAME, null)
SecurityType.JWT_BEARER -> { /* not specified for OpenApi 2.0 */ }
}
}
}
1 change: 1 addition & 0 deletions restdocs-api-spec-restassured/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@ dependencies {
}
testImplementation("org.junit.jupiter:junit-jupiter-engine:$junitVersion")
testImplementation("org.junit-pioneer:junit-pioneer:0.3.0")
testImplementation("org.springframework.boot:spring-boot-starter-validation:$springBootVersion")
testImplementation("org.springframework.boot:spring-boot-starter-hateoas:$springBootVersion")
}

Original file line number Diff line number Diff line change
@@ -2,8 +2,8 @@ package com.epages.restdocs.apispec

import org.springframework.restdocs.operation.preprocess.OperationRequestPreprocessor
import org.springframework.restdocs.operation.preprocess.OperationResponsePreprocessor
import org.springframework.restdocs.restassured3.RestAssuredRestDocumentation
import org.springframework.restdocs.restassured3.RestDocumentationFilter
import org.springframework.restdocs.restassured.RestAssuredRestDocumentation
import org.springframework.restdocs.restassured.RestDocumentationFilter
import org.springframework.restdocs.snippet.Snippet
import java.util.function.Function

Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ package com.epages.restdocs.apispec

import com.epages.restdocs.apispec.ResourceDocumentation.parameterWithName
import com.epages.restdocs.apispec.ResourceDocumentation.resource
import jakarta.validation.constraints.NotEmpty
import org.hibernate.validator.constraints.Length
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
@@ -11,9 +12,10 @@ import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
import org.springframework.context.ConfigurableApplicationContext
import org.springframework.hateoas.EntityModel
import org.springframework.hateoas.IanaLinkRelations
import org.springframework.hateoas.Link
import org.springframework.hateoas.Resource
import org.springframework.hateoas.mvc.BasicLinkBuilder
import org.springframework.hateoas.server.mvc.BasicLinkBuilder.linkToCurrentMapping
import org.springframework.http.HttpHeaders.ACCEPT
import org.springframework.http.HttpHeaders.CONTENT_TYPE
import org.springframework.http.ResponseEntity
@@ -29,7 +31,6 @@ import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestHeader
import org.springframework.web.bind.annotation.RestController
import java.util.UUID
import javax.validation.constraints.NotEmpty

@ExtendWith(SpringExtension::class)
@WebMvcTest
@@ -71,17 +72,17 @@ open class ResourceSnippetIntegrationTest {
@PathVariable otherId: Int?,
@RequestHeader("X-Custom-Header") customHeader: String,
@RequestBody testDataHolder: TestDataHolder
): ResponseEntity<Resource<TestDataHolder>> {
val resource = Resource(testDataHolder.copy(id = UUID.randomUUID().toString()))
val link = BasicLinkBuilder.linkToCurrentMapping().slash("some").slash(someId).slash("other").slash(otherId).toUri().toString()
resource.add(Link(link, Link.REL_SELF))
resource.add(Link(link, "multiple"))
resource.add(Link(link, "multiple"))
): ResponseEntity<EntityModel<TestDataHolder>> {
val resource = EntityModel.of(testDataHolder.copy(id = UUID.randomUUID().toString()))
val link = linkToCurrentMapping().slash("some").slash(someId).slash("other").slash(otherId).toUri().toString()
resource.add(Link.of(link, IanaLinkRelations.SELF))
resource.add(Link.of(link, "multiple"))
resource.add(Link.of(link, "multiple"))

return ResponseEntity
.ok()
.header("X-Custom-Header", customHeader)
.body<Resource<TestDataHolder>>(resource)
.body<EntityModel<TestDataHolder>>(resource)
}
}
}
Original file line number Diff line number Diff line change
@@ -25,8 +25,8 @@ import org.springframework.restdocs.payload.PayloadDocumentation.responseFields
import org.springframework.restdocs.payload.PayloadDocumentation.subsectionWithPath
import org.springframework.restdocs.request.RequestDocumentation.parameterWithName
import org.springframework.restdocs.request.RequestDocumentation.pathParameters
import org.springframework.restdocs.restassured3.RestAssuredRestDocumentation
import org.springframework.restdocs.restassured3.RestDocumentationFilter
import org.springframework.restdocs.restassured.RestAssuredRestDocumentation
import org.springframework.restdocs.restassured.RestDocumentationFilter
import java.io.File

@ExtendWith(RestDocumentationExtension::class)
2 changes: 2 additions & 0 deletions restdocs-api-spec-webtestclient/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -22,6 +22,8 @@ dependencies {
testImplementation("org.springframework.boot:spring-boot-starter-test:$springBootVersion") {
exclude("junit")
}
testImplementation("org.hibernate.validator:hibernate-validator:8.0.0.Final")
testImplementation("org.springframework.boot:spring-boot-starter-validation:$springBootVersion")
testImplementation("org.junit.jupiter:junit-jupiter-engine:$junitVersion")
testImplementation("org.junit-pioneer:junit-pioneer:0.3.0")
testImplementation("org.springframework.boot:spring-boot-starter-web:$springBootVersion")
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ package com.epages.restdocs.apispec

import com.epages.restdocs.apispec.ResourceDocumentation.parameterWithName
import com.epages.restdocs.apispec.ResourceDocumentation.resource
import jakarta.validation.constraints.NotEmpty
import org.hibernate.validator.constraints.Length
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.boot.SpringApplication
@@ -24,7 +25,6 @@ import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestHeader
import org.springframework.web.bind.annotation.RestController
import java.util.UUID
import javax.validation.constraints.NotEmpty

@ExtendWith(SpringExtension::class)
@AutoConfigureRestDocs
2 changes: 2 additions & 0 deletions restdocs-api-spec/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -18,6 +18,8 @@ dependencies {
implementation(kotlin("reflect"))

implementation("org.springframework.restdocs:spring-restdocs-core:$springRestDocsVersion")
implementation("org.springframework.boot:spring-boot-starter-web:$springBootVersion")
implementation("org.springframework.boot:spring-boot-starter-validation:$springBootVersion")
implementation("com.fasterxml.jackson.core:jackson-databind:$jacksonVersion")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonVersion")

Original file line number Diff line number Diff line change
@@ -12,10 +12,11 @@ import org.springframework.restdocs.payload.FieldDescriptor
import org.springframework.restdocs.payload.JsonFieldType
import org.springframework.restdocs.payload.RequestFieldsSnippet
import org.springframework.restdocs.payload.ResponseFieldsSnippet
import org.springframework.restdocs.request.FormParametersSnippet
import org.springframework.restdocs.request.ParameterDescriptor
import org.springframework.restdocs.request.PathParametersSnippet
import org.springframework.restdocs.request.QueryParametersSnippet
import org.springframework.restdocs.request.RequestDocumentation.parameterWithName
import org.springframework.restdocs.request.RequestParametersSnippet

internal object DescriptorValidator {

@@ -46,14 +47,23 @@ internal object DescriptorValidator {
)
)
}

validateIfDescriptorsPresent(
requestParameters,
queryParameters,
operation
) {
QueryParameterSnippetWrapper(
toParameterDescriptors(
queryParameters
)
)
}
validateIfDescriptorsPresent(
formParameters,
operation
) {
RequestParameterSnippetWrapper(
FormParameterSnippetWrapper(
toParameterDescriptors(
requestParameters
formParameters
)
)
}
@@ -159,8 +169,16 @@ internal object DescriptorValidator {
}
}

private class RequestParameterSnippetWrapper(descriptors: List<ParameterDescriptor>) :
RequestParametersSnippet(descriptors),
private class FormParameterSnippetWrapper(descriptors: List<ParameterDescriptor>) :
FormParametersSnippet(descriptors),
ValidateableSnippet {
override fun validate(operation: Operation) {
super.createModel(operation)
}
}

private class QueryParameterSnippetWrapper(descriptors: List<ParameterDescriptor>) :
QueryParametersSnippet(descriptors),
ValidateableSnippet {
override fun validate(operation: Operation) {
super.createModel(operation)
Loading

0 comments on commit 415f402

Please sign in to comment.