diff --git a/build.gradle b/build.gradle index cd5d270ca119..8a3207ccc859 100644 --- a/build.gradle +++ b/build.gradle @@ -1,16 +1,16 @@ plugins { - id 'io.spring.dependency-management' version '1.0.9.RELEASE' apply false - id 'io.spring.nohttp' version '0.0.5.RELEASE' - id 'org.jetbrains.kotlin.jvm' version '1.5.21' apply false - id 'org.jetbrains.dokka' version '0.10.1' apply false - id 'org.asciidoctor.jvm.convert' version '3.1.0' - id 'org.asciidoctor.jvm.pdf' version '3.1.0' - id 'de.undercouch.download' version '4.1.1' - id "io.freefair.aspectj" version '5.1.1' apply false - id "com.github.ben-manes.versions" version '0.28.0' - id "com.github.johnrengelman.shadow" version "6.1.0" apply false - id "me.champeau.jmh" version "0.6.4" apply false - id "org.jetbrains.kotlin.plugin.serialization" version "1.5.21" apply false + id 'io.spring.dependency-management' version '1.0.11.RELEASE' apply false + id 'io.spring.nohttp' version '0.0.10' + id 'org.jetbrains.kotlin.jvm' version '1.5.30' apply false + id 'org.jetbrains.dokka' version '1.5.0' apply false + id 'org.asciidoctor.jvm.convert' version '3.3.2' + id 'org.asciidoctor.jvm.pdf' version '3.3.2' + id 'de.undercouch.download' version '4.1.2' + id "io.freefair.aspectj" version '6.1.0' apply false + id "com.github.ben-manes.versions" version '0.39.0' + id "com.github.johnrengelman.shadow" version '7.0.0' apply false + id "me.champeau.jmh" version "0.6.6" apply false + id "org.jetbrains.kotlin.plugin.serialization" version "1.5.30" apply false id "org.unbroken-dome.xjc" version '2.0.0' apply false } @@ -27,16 +27,16 @@ configure(allprojects) { project -> dependencyManagement { imports { - mavenBom "com.fasterxml.jackson:jackson-bom:2.12.4" - mavenBom "io.netty:netty-bom:4.1.65.Final" - mavenBom "io.projectreactor:reactor-bom:2020.0.9" + mavenBom "com.fasterxml.jackson:jackson-bom:2.12.5" + mavenBom "io.netty:netty-bom:4.1.68.Final" + mavenBom "io.projectreactor:reactor-bom:2020.0.11" mavenBom "io.r2dbc:r2dbc-bom:Arabba-SR10" mavenBom "io.rsocket:rsocket-bom:1.1.1" mavenBom "org.eclipse.jetty:jetty-bom:9.4.43.v20210629" - mavenBom "org.jetbrains.kotlin:kotlin-bom:1.5.21" - mavenBom "org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.5.1" - mavenBom "org.jetbrains.kotlinx:kotlinx-serialization-bom:1.2.1" - mavenBom "org.junit:junit-bom:5.7.2" + mavenBom "org.jetbrains.kotlin:kotlin-bom:1.5.30" + mavenBom "org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.5.2" + mavenBom "org.jetbrains.kotlinx:kotlinx-serialization-bom:1.2.2" + mavenBom "org.junit:junit-bom:5.8.0" } dependencies { dependencySet(group: 'org.apache.logging.log4j', version: '2.14.1') { @@ -67,7 +67,8 @@ configure(allprojects) { project -> dependency "io.reactivex:rxjava:1.3.8" dependency "io.reactivex:rxjava-reactive-streams:1.2.1" dependency "io.reactivex.rxjava2:rxjava:2.2.21" - dependency "io.reactivex.rxjava3:rxjava:3.0.13" + dependency "io.reactivex.rxjava3:rxjava:3.1.1" + dependency "io.smallrye.reactive:mutiny:1.0.0" dependency "io.projectreactor.tools:blockhound:1.0.4.RELEASE" dependency "com.caucho:hessian:4.0.63" @@ -75,10 +76,10 @@ configure(allprojects) { project -> dependency("com.fasterxml.woodstox:woodstox-core:6.2.6") { exclude group: "stax", name: "stax-api" } - dependency "com.google.code.gson:gson:2.8.7" + dependency "com.google.code.gson:gson:2.8.8" dependency "com.google.protobuf:protobuf-java-util:3.17.3" dependency "com.googlecode.protobuf-java-format:protobuf-java-format:1.4" - dependency("com.thoughtworks.xstream:xstream:1.4.17") { + dependency("com.thoughtworks.xstream:xstream:1.4.18") { exclude group: "xpp3", name: "xpp3_min" exclude group: "xmlpull", name: "xmlpull" } @@ -127,18 +128,18 @@ configure(allprojects) { project -> dependency "org.webjars:webjars-locator-core:0.47" dependency "org.webjars:underscorejs:1.8.3" - dependencySet(group: 'org.apache.tomcat', version: '9.0.50') { + dependencySet(group: 'org.apache.tomcat', version: '9.0.52') { entry 'tomcat-util' entry('tomcat-websocket') { exclude group: "org.apache.tomcat", name: "tomcat-websocket-api" exclude group: "org.apache.tomcat", name: "tomcat-servlet-api" } } - dependencySet(group: 'org.apache.tomcat.embed', version: '9.0.50') { + dependencySet(group: 'org.apache.tomcat.embed', version: '9.0.52') { entry 'tomcat-embed-core' entry 'tomcat-embed-websocket' } - dependencySet(group: 'io.undertow', version: '2.2.8.Final') { + dependencySet(group: 'io.undertow', version: '2.2.10.Final') { entry 'undertow-core' entry('undertow-websockets-jsr') { exclude group: "org.jboss.spec.javax.websocket", name: "jboss-websocket-api_1.1_spec" @@ -196,18 +197,18 @@ configure(allprojects) { project -> exclude group: "org.hamcrest", name: "hamcrest-core" } } - dependencySet(group: 'org.mockito', version: '3.11.0') { + dependencySet(group: 'org.mockito', version: '3.12.4') { entry('mockito-core') { exclude group: "org.hamcrest", name: "hamcrest-core" } entry 'mockito-junit-jupiter' } - dependency "io.mockk:mockk:1.11.0" + dependency "io.mockk:mockk:1.12.0" - dependency("net.sourceforge.htmlunit:htmlunit:2.51.0") { + dependency("net.sourceforge.htmlunit:htmlunit:2.52.0") { exclude group: "commons-logging", name: "commons-logging" } - dependency("org.seleniumhq.selenium:htmlunit-driver:2.51.0") { + dependency("org.seleniumhq.selenium:htmlunit-driver:2.52.0") { exclude group: "commons-logging", name: "commons-logging" } dependency("org.seleniumhq.selenium:selenium-java:3.141.59") { @@ -215,7 +216,7 @@ configure(allprojects) { project -> exclude group: "io.netty", name: "netty" } dependency "org.skyscreamer:jsonassert:1.5.0" - dependency "com.jayway.jsonpath:json-path:2.5.0" + dependency "com.jayway.jsonpath:json-path:2.6.0" dependency "org.bouncycastle:bcpkix-jdk15on:1.66" dependencySet(group: 'org.apache.tiles', version: '3.0.8') { @@ -312,6 +313,8 @@ configure([rootProject] + javaProjects) { project -> pluginManager.withPlugin("kotlin") { apply plugin: "org.jetbrains.dokka" + apply from: "${rootDir}/gradle/docs-dokka.gradle" + compileKotlin { kotlinOptions { languageVersion = "1.3" @@ -336,23 +339,25 @@ configure([rootProject] + javaProjects) { project -> } checkstyle { - toolVersion = "8.44" + toolVersion = "8.45.1" configDirectory.set(rootProject.file("src/checkstyle")) } dependencies { - testCompile("org.junit.jupiter:junit-jupiter-api") - testCompile("org.junit.jupiter:junit-jupiter-params") - testCompile("org.mockito:mockito-core") - testCompile("org.mockito:mockito-junit-jupiter") - testCompile("io.mockk:mockk") - testCompile("org.assertj:assertj-core") + testImplementation("org.junit.jupiter:junit-jupiter-api") + testImplementation("org.junit.jupiter:junit-jupiter-params") + testImplementation("org.junit.platform:junit-platform-suite-api") + testImplementation("org.mockito:mockito-core") + testImplementation("org.mockito:mockito-junit-jupiter") + testImplementation("io.mockk:mockk") + testImplementation("org.assertj:assertj-core") // Pull in the latest JUnit 5 Launcher API to ensure proper support in IDEs. - testRuntime("org.junit.platform:junit-platform-launcher") - testRuntime("org.junit.jupiter:junit-jupiter-engine") - testRuntime("org.apache.logging.log4j:log4j-core") - testRuntime("org.apache.logging.log4j:log4j-slf4j-impl") - testRuntime("org.apache.logging.log4j:log4j-jul") + testRuntimeOnly("org.junit.platform:junit-platform-launcher") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine") + testRuntimeOnly("org.junit.platform:junit-platform-suite-engine") + testRuntimeOnly("org.apache.logging.log4j:log4j-core") + testRuntimeOnly("org.apache.logging.log4j:log4j-slf4j-impl") + testRuntimeOnly("org.apache.logging.log4j:log4j-jul") // JSR-305 only used for non-required meta-annotations compileOnly("com.google.code.findbugs:jsr305") testCompileOnly("com.google.code.findbugs:jsr305") @@ -363,7 +368,7 @@ configure([rootProject] + javaProjects) { project -> "https://docs.oracle.com/javase/8/docs/api/", "https://docs.oracle.com/javaee/7/api/", "https://docs.oracle.com/cd/E13222_01/wls/docs90/javadocs/", // CommonJ - "https://www.ibm.com/support/knowledgecenter/SS7JFU_8.5.5/com.ibm.websphere.javadoc.doc/web/apidocs/", + "https://www.ibm.com/docs/api/v1/content/SSEQTP_8.5.5/com.ibm.websphere.javadoc.doc/web/apidocs/", "https://glassfish.java.net/nonav/docs/v3/api/", "https://docs.jboss.org/jbossas/javadoc/4.0.5/connector/", "https://docs.jboss.org/jbossas/javadoc/7.1.2.Final/", @@ -378,7 +383,10 @@ configure([rootProject] + javaProjects) { project -> "https://hc.apache.org/httpcomponents-client-5.1.x/current/httpclient5/apidocs/", "https://projectreactor.io/docs/test/release/api/", "https://junit.org/junit4/javadoc/4.13.2/", - "https://junit.org/junit5/docs/5.7.2/api/" + "https://junit.org/junit5/docs/5.8.0/api/", + "https://www.reactive-streams.org/reactive-streams-1.0.3-javadoc/", + "https://javadoc.io/static/io.rsocket/rsocket-core/1.1.1/", + "https://r2dbc.io/spec/0.8.5.RELEASE/api/" ] as String[] } diff --git a/buildSrc/src/main/java/org/springframework/build/compile/CompilerConventionsPlugin.java b/buildSrc/src/main/java/org/springframework/build/compile/CompilerConventionsPlugin.java index 5284df28f124..f2424c549e50 100644 --- a/buildSrc/src/main/java/org/springframework/build/compile/CompilerConventionsPlugin.java +++ b/buildSrc/src/main/java/org/springframework/build/compile/CompilerConventionsPlugin.java @@ -32,6 +32,7 @@ * * @author Brian Clozel * @author Sam Brannen + * @author Sebastien Deleuze */ public class CompilerConventionsPlugin implements Plugin { @@ -43,7 +44,8 @@ public class CompilerConventionsPlugin implements Plugin { List commonCompilerArgs = Arrays.asList( "-Xlint:serial", "-Xlint:cast", "-Xlint:classfile", "-Xlint:dep-ann", "-Xlint:divzero", "-Xlint:empty", "-Xlint:finally", "-Xlint:overrides", - "-Xlint:path", "-Xlint:processing", "-Xlint:static", "-Xlint:try", "-Xlint:-options" + "-Xlint:path", "-Xlint:processing", "-Xlint:static", "-Xlint:try", "-Xlint:-options", + "-parameters" ); COMPILER_ARGS = new ArrayList<>(); COMPILER_ARGS.addAll(commonCompilerArgs); @@ -54,7 +56,7 @@ public class CompilerConventionsPlugin implements Plugin { TEST_COMPILER_ARGS = new ArrayList<>(); TEST_COMPILER_ARGS.addAll(commonCompilerArgs); TEST_COMPILER_ARGS.addAll(Arrays.asList("-Xlint:-varargs", "-Xlint:-fallthrough", "-Xlint:-rawtypes", - "-Xlint:-deprecation", "-Xlint:-unchecked", "-parameters")); + "-Xlint:-deprecation", "-Xlint:-unchecked")); } @Override diff --git a/buildSrc/src/main/java/org/springframework/build/optional/OptionalDependenciesPlugin.java b/buildSrc/src/main/java/org/springframework/build/optional/OptionalDependenciesPlugin.java index 55537c2d8259..a7e7101daee7 100644 --- a/buildSrc/src/main/java/org/springframework/build/optional/OptionalDependenciesPlugin.java +++ b/buildSrc/src/main/java/org/springframework/build/optional/OptionalDependenciesPlugin.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -19,6 +19,7 @@ import org.gradle.api.Plugin; import org.gradle.api.Project; import org.gradle.api.artifacts.Configuration; +import org.gradle.api.attributes.Usage; import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.plugins.JavaPluginConvention; import org.gradle.api.tasks.SourceSetContainer; @@ -28,7 +29,7 @@ /** * A {@code Plugin} that adds support for Maven-style optional dependencies. Creates a new * {@code optional} configuration. The {@code optional} configuration is part of the - * project's compile and runtime classpath's but does not affect the classpath of + * project's compile and runtime classpaths but does not affect the classpath of * dependent projects. * * @author Andy Wilkinson @@ -43,22 +44,16 @@ public class OptionalDependenciesPlugin implements Plugin { @Override public void apply(Project project) { Configuration optional = project.getConfigurations().create("optional"); + optional.setCanBeConsumed(false); + optional.setCanBeResolved(false); project.getPlugins().withType(JavaPlugin.class, (javaPlugin) -> { - SourceSetContainer sourceSets = project.getConvention() - .getPlugin(JavaPluginConvention.class).getSourceSets(); + SourceSetContainer sourceSets = project.getConvention().getPlugin(JavaPluginConvention.class) + .getSourceSets(); sourceSets.all((sourceSet) -> { - sourceSet.setCompileClasspath( - sourceSet.getCompileClasspath().plus(optional)); - sourceSet.setRuntimeClasspath( - sourceSet.getRuntimeClasspath().plus(optional)); + project.getConfigurations().getByName(sourceSet.getCompileClasspathConfigurationName()).extendsFrom(optional); + project.getConfigurations().getByName(sourceSet.getRuntimeClasspathConfigurationName()).extendsFrom(optional); }); }); - project.getPlugins().withType(EclipsePlugin.class, (eclipePlugin) -> { - project.getExtensions().getByType(EclipseModel.class) - .classpath((classpath) -> { - classpath.getPlusConfigurations().add(optional); - }); - }); } } \ No newline at end of file diff --git a/ci/config/changelog-generator.yml b/ci/config/changelog-generator.yml index 248e58db739e..a029e25582e4 100644 --- a/ci/config/changelog-generator.yml +++ b/ci/config/changelog-generator.yml @@ -4,7 +4,7 @@ changelog: - title: ":star: New Features" labels: - "type: enhancement" - - title: ":beetle: Bug Fixes" + - title: ":lady_beetle: Bug Fixes" labels: - "type: bug" - "type: regression" diff --git a/ci/images/ci-image/Dockerfile b/ci/images/ci-image/Dockerfile index 1ce41f37a932..df1be9f33457 100644 --- a/ci/images/ci-image/Dockerfile +++ b/ci/images/ci-image/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:focal-20210119 +FROM ubuntu:focal-20210827 ADD setup.sh /setup.sh ADD get-jdk-url.sh /get-jdk-url.sh @@ -6,6 +6,6 @@ RUN ./setup.sh java8 ENV JAVA_HOME /opt/openjdk/java8 ENV JDK11 /opt/openjdk/java11 -ENV JDK15 /opt/openjdk/java15 +ENV JDK16 /opt/openjdk/java16 ENV PATH $JAVA_HOME/bin:$PATH diff --git a/ci/images/get-jdk-url.sh b/ci/images/get-jdk-url.sh index f4f3ab84cf40..e170d55171c3 100755 --- a/ci/images/get-jdk-url.sh +++ b/ci/images/get-jdk-url.sh @@ -3,13 +3,13 @@ set -e case "$1" in java8) - echo "https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u282-b08/OpenJDK8U-jdk_x64_linux_hotspot_8u282b08.tar.gz" + echo "https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u302-b08/OpenJDK8U-jdk_x64_linux_hotspot_8u302b08.tar.gz" ;; java11) - echo "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.10%2B9/OpenJDK11U-jdk_x64_linux_hotspot_11.0.10_9.tar.gz" + echo "https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.12%2B7/OpenJDK11U-jdk_x64_linux_hotspot_11.0.12_7.tar.gz" ;; - java15) - echo "https://github.com/AdoptOpenJDK/openjdk15-binaries/releases/download/jdk-15.0.2%2B7/OpenJDK15U-jdk_x64_linux_hotspot_15.0.2_7.tar.gz" + java16) + echo "https://github.com/adoptium/temurin16-binaries/releases/download/jdk-16.0.2%2B7/OpenJDK16U-jdk_x64_linux_hotspot_16.0.2_7.tar.gz" ;; *) echo $"Unknown java version" diff --git a/ci/images/setup.sh b/ci/images/setup.sh index b226ab7de75c..ff18f849f40c 100755 --- a/ci/images/setup.sh +++ b/ci/images/setup.sh @@ -22,7 +22,7 @@ curl --output /opt/concourse-release-scripts.jar https://repo.spring.io/release/ mkdir -p /opt/openjdk pushd /opt/openjdk > /dev/null -for jdk in java8 java11 java15 +for jdk in java8 java11 java16 do JDK_URL=$( /get-jdk-url.sh $jdk ) mkdir $jdk diff --git a/ci/pipeline.yml b/ci/pipeline.yml index eb752fe705cc..b9fe3db2f917 100644 --- a/ci/pipeline.yml +++ b/ci/pipeline.yml @@ -2,7 +2,7 @@ anchors: git-repo-resource-source: &git-repo-resource-source uri: ((github-repo)) username: ((github-username)) - password: ((github-password)) + password: ((github-ci-release-token)) branch: ((branch)) gradle-enterprise-task-params: &gradle-enterprise-task-params GRADLE_ENTERPRISE_ACCESS_KEY: ((gradle_enterprise_secret_access_key)) @@ -45,7 +45,7 @@ resource_types: type: registry-image source: repository: springio/artifactory-resource - tag: 0.0.13 + tag: 0.0.17 - name: github-status-resource type: registry-image source: @@ -119,14 +119,14 @@ resources: access_token: ((github-ci-status-token)) branch: ((branch)) context: jdk11-build -- name: repo-status-jdk15-build +- name: repo-status-jdk16-build type: github-status-resource icon: eye-check-outline source: repository: ((github-repo-name)) access_token: ((github-ci-status-token)) branch: ((branch)) - context: jdk15-build + context: jdk16-build - name: slack-alert type: slack-notification icon: slack @@ -244,7 +244,7 @@ jobs: <<: *slack-fail-params - put: repo-status-jdk11-build params: { state: "success", commit: "git-repo" } -- name: jdk15-build +- name: jdk16-build serial: true public: true plan: @@ -252,7 +252,7 @@ jobs: - get: git-repo - get: every-morning trigger: true - - put: repo-status-jdk15-build + - put: repo-status-jdk16-build params: { state: "pending", commit: "git-repo" } - do: - task: check-project @@ -265,12 +265,12 @@ jobs: <<: *build-project-task-params on_failure: do: - - put: repo-status-jdk15-build + - put: repo-status-jdk16-build params: { state: "failure", commit: "git-repo" } - put: slack-alert params: <<: *slack-fail-params - - put: repo-status-jdk15-build + - put: repo-status-jdk16-build params: { state: "success", commit: "git-repo" } - name: build-pull-requests serial: true @@ -292,7 +292,7 @@ jobs: privileged: true timeout: ((task-timeout)) params: - <<: *build-project-task-params + BRANCH: ((branch)) on_success: put: git-pull-request params: @@ -453,7 +453,7 @@ jobs: groups: - name: "builds" - jobs: ["build", "jdk11-build", "jdk15-build"] + jobs: ["build", "jdk11-build", "jdk16-build"] - name: "releases" jobs: ["stage-milestone", "stage-rc", "stage-release", "promote-milestone", "promote-rc", "promote-release", "create-github-release"] - name: "ci-images" diff --git a/ci/scripts/stage-version.sh b/ci/scripts/stage-version.sh index 0b285de014bf..73c57755451c 100755 --- a/ci/scripts/stage-version.sh +++ b/ci/scripts/stage-version.sh @@ -29,8 +29,8 @@ fi echo "Staging $stageVersion (next version will be $nextVersion)" sed -i "s/version=$snapshotVersion/version=$stageVersion/" gradle.properties -git config user.name "Spring Buildmaster" > /dev/null -git config user.email "buildmaster@springframework.org" > /dev/null +git config user.name "Spring Builds" > /dev/null +git config user.email "spring-builds@users.noreply.github.com" > /dev/null git add gradle.properties > /dev/null git commit -m"Release v$stageVersion" > /dev/null git tag -a "v$stageVersion" -m"Release v$stageVersion" > /dev/null diff --git a/gradle.properties b/gradle.properties index c05ae8cc9dd2..13ade94eb912 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -version=5.3.9-SNAPSHOT +version=5.3.10 org.gradle.jvmargs=-Xmx1536M org.gradle.caching=true org.gradle.parallel=true diff --git a/gradle/docs-dokka.gradle b/gradle/docs-dokka.gradle new file mode 100644 index 000000000000..ef06f904185c --- /dev/null +++ b/gradle/docs-dokka.gradle @@ -0,0 +1,30 @@ +tasks.findByName("dokkaHtmlPartial")?.configure { + outputDirectory.set(new File(buildDir, "docs/kdoc")) + dokkaSourceSets { + configureEach { + sourceRoots.setFrom(file("src/main/kotlin")) + classpath.from(sourceSets["main"].runtimeClasspath) + externalDocumentationLink { + url.set(new URL("https://docs.spring.io/spring-framework/docs/current/javadoc-api/")) + } + externalDocumentationLink { + url.set(new URL("https://projectreactor.io/docs/core/release/api/")) + } + externalDocumentationLink { + url.set(new URL("https://www.reactive-streams.org/reactive-streams-1.0.3-javadoc/")) + } + externalDocumentationLink { + url.set(new URL("https://kotlin.github.io/kotlinx.coroutines/")) + } + externalDocumentationLink { + url.set(new URL("https://hamcrest.org/JavaHamcrest/javadoc/2.1/")) + } + externalDocumentationLink { + url.set(new URL("https://javadoc.io/doc/javax.servlet/javax.servlet-api/latest/")) + } + externalDocumentationLink { + url.set(new URL("https://javadoc.io/static/io.rsocket/rsocket-core/1.1.1/")) + } + } + } +} diff --git a/gradle/docs.gradle b/gradle/docs.gradle index 085d291e0742..bfb26d152b9c 100644 --- a/gradle/docs.gradle +++ b/gradle/docs.gradle @@ -61,57 +61,13 @@ task api(type: Javadoc) { /** * Produce KDoc for all Spring Framework modules in "build/docs/kdoc" */ -dokka { - dependsOn { - tasks.getByName("api") - } - - doFirst { - configuration { - classpath = moduleProjects.collect { project -> project.jar.outputs.files.getFiles() }.flatten() - classpath += files(moduleProjects.collect { it.sourceSets.main.compileClasspath }) - - moduleProjects.findAll { - it.pluginManager.hasPlugin("kotlin") - }.each { project -> - def kotlinDirs = project.sourceSets.main.kotlin.srcDirs.collect() - kotlinDirs -= project.sourceSets.main.java.srcDirs - kotlinDirs.each { dir -> - if (dir.exists()) { - sourceRoot { - path = dir.path - } - } - } - } - } - } - - outputFormat = "html" - outputDirectory = "$buildDir/docs/kdoc" - - configuration { - moduleName = "spring-framework" - - externalDocumentationLink { - url = new URL("https://docs.spring.io/spring-framework/docs/$version/javadoc-api/") - packageListUrl = new File(buildDir, "docs/javadoc/package-list").toURI().toURL() - } - externalDocumentationLink { - url = new URL("https://projectreactor.io/docs/core/release/api/") - } - externalDocumentationLink { - url = new URL("https://www.reactive-streams.org/reactive-streams-1.0.1-javadoc/") - } -/* - This link causes errors, removing to fix the build. - externalDocumentationLink { - url = new URL("https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/") - } -*/ - externalDocumentationLink { - url = new URL("https://r2dbc.io/spec/0.8.3.RELEASE/api/") +pluginManager.withPlugin("kotlin") { + tasks.dokkaHtmlMultiModule.configure { + dependsOn { + tasks.getByName("api") } + moduleName.set("spring-framework") + outputDirectory.set(project.file("$buildDir/docs/kdoc")) } } @@ -139,7 +95,7 @@ asciidoctorj { icons: 'font', idprefix: '', idseparator: '-', - docinfo: 'shared', + docinfo: 'shared,private-header', // https://docs.asciidoctor.org/asciidoctor/latest/docinfo/ revnumber: project.version, sectanchors: '', sectnums: '', @@ -163,9 +119,6 @@ asciidoctorj { asciidoctor { baseDirFollowsSourceDir() configurations 'asciidoctorExt' - attributes([ - noheader: '' // custom header in docinfo-header.html - ]) sources { include '*.adoc' } @@ -196,7 +149,7 @@ asciidoctorPdf { /** * Zip all docs (API and reference) into a single archive */ -task docsZip(type: Zip, dependsOn: ['api', 'asciidoctor', 'asciidoctorPdf', 'dokka']) { +task docsZip(type: Zip, dependsOn: ['api', 'asciidoctor', 'asciidoctorPdf', 'dokkaHtmlMultiModule']) { group = "Distribution" description = "Builds -${archiveClassifier} archive containing api and reference " + "for deployment at https://docs.spring.io/spring-framework/docs." @@ -215,7 +168,7 @@ task docsZip(type: Zip, dependsOn: ['api', 'asciidoctor', 'asciidoctorPdf', 'dok from ("$asciidoctorPdf.outputDir") { into "reference/pdf" } - from (dokka) { + from (dokkaHtmlMultiModule.outputDirectory) { into "kdoc-api" } } @@ -272,11 +225,11 @@ task distZip(type: Zip, dependsOn: [docsZip, schemaZip]) { expand(copyright: new Date().format("yyyy"), version: project.version) } - from(zipTree(docsZip.archivePath)) { + from(zipTree(docsZip.archiveFile)) { into "${baseDir}/docs" } - from(zipTree(schemaZip.archivePath)) { + from(zipTree(schemaZip.archiveFile)) { into "${baseDir}/schema" } diff --git a/gradle/ide.gradle b/gradle/ide.gradle index 7db543d3bc4d..af4664e06018 100644 --- a/gradle/ide.gradle +++ b/gradle/ide.gradle @@ -1,7 +1,7 @@ import org.gradle.plugins.ide.eclipse.model.ProjectDependency import org.gradle.plugins.ide.eclipse.model.SourceFolder -apply plugin: "eclipse" +apply plugin: 'eclipse' eclipse.jdt { sourceCompatibility = 1.8 @@ -18,40 +18,45 @@ eclipse.classpath.file.whenMerged { classpath -> if (matcher) { def projectName = matcher[0][1] def path = "/${projectName}" - if(!classpath.entries.find { e -> e instanceof ProjectDependency && e.path == path }) { - def dependency = new ProjectDependency(path) - dependency.exported = true - classpath.entries.add(dependency) + if (!classpath.entries.find { e -> e instanceof ProjectDependency && e.path == path }) { + def recursiveDependency = entry.path.matches('.+/' + projectName + '/build/([^/]+/)+(?:main|test)') + // Avoid recursive dependency on current project. + if (!recursiveDependency) { + classpath.entries.add(new ProjectDependency(path)) + } } classpath.entries.remove(entry) } } + + // Remove any remaining direct depencencies on JARs in the build/libs folder + // except Spring's spring-cglib-repack and spring-objenesis-repack JARs. classpath.entries.removeAll { entry -> (entry.path =~ /(?!.*?repack.*\.jar).*?\/([^\/]+)\/build\/libs\/[^\/]+\.jar/) } } // Use separate main/test outputs (prevents WTP from packaging test classes) -eclipse.classpath.defaultOutputDir = file(project.name+"/bin/eclipse") +eclipse.classpath.defaultOutputDir = file(project.name + '/bin/eclipse') eclipse.classpath.file.beforeMerged { classpath -> classpath.entries.findAll{ it instanceof SourceFolder }.each { - if (it.output.startsWith("bin/")) { + if (it.output.startsWith('bin/')) { it.output = null } } } -eclipse.classpath.file.whenMerged { classpath -> - classpath.entries.findAll{ it instanceof SourceFolder }.each { - it.output = "bin/" + it.path.split("/")[1] +eclipse.classpath.file.whenMerged { + entries.findAll{ it instanceof SourceFolder }.each { + it.output = 'bin/' + it.path.split('/')[1] } } // Ensure project dependencies come after 3rd-party libs (SPR-11836) // https://jira.spring.io/browse/SPR-11836 -eclipse.classpath.file.whenMerged { classpath -> - classpath.entries.findAll { it instanceof ProjectDependency }.each { +eclipse.classpath.file.whenMerged { + entries.findAll { it instanceof ProjectDependency }.each { // delete from original position - classpath.entries.remove(it) + entries.remove(it) // append to end of classpath - classpath.entries.add(it) + entries.add(it) } } @@ -65,46 +70,41 @@ eclipse.classpath.file.whenMerged { } // Allow projects to be used as WTP modules -eclipse.project.natures "org.eclipse.wst.common.project.facet.core.nature" +eclipse.project.natures 'org.eclipse.wst.common.project.facet.core.nature' // Include project specific settings task eclipseSettings(type: Copy) { from rootProject.files( - "src/eclipse/org.eclipse.jdt.ui.prefs", - "src/eclipse/org.eclipse.wst.common.project.facet.core.xml") + 'src/eclipse/org.eclipse.jdt.ui.prefs', + 'src/eclipse/org.eclipse.wst.common.project.facet.core.xml') into project.file('.settings/') outputs.upToDateWhen { false } } -task eclipseWstComponent(type: Copy) { - from rootProject.files( - "src/eclipse/org.eclipse.wst.common.component") +task eclipseJdtSettings(type: Copy) { + from rootProject.file('src/eclipse/org.eclipse.jdt.core.prefs') into project.file('.settings/') - expand(deployname: project.name) outputs.upToDateWhen { false } } -task eclipseJdtPrepare(type: Copy) { - from rootProject.file("src/eclipse/org.eclipse.jdt.core.prefs") - into project.file(".settings/") - outputs.upToDateWhen { false } -} - -task cleanEclipseJdtUi(type: Delete) { - delete project.file(".settings/org.eclipse.jdt.core.prefs") - delete project.file(".settings/org.eclipse.jdt.ui.prefs") - delete project.file(".settings/org.eclipse.wst.common.component") - delete project.file(".settings/org.eclipse.wst.common.project.facet.core.xml") +task eclipseBuildship { + dependsOn eclipseSettings, eclipseJdtSettings } -task eclipseBuildship(type: Copy) { - from rootProject.files( - "src/eclipse/org.eclipse.jdt.ui.prefs", - "src/eclipse/org.eclipse.jdt.core.prefs") +task eclipseWstComponentSettings(type: Copy) { + from rootProject.files('src/eclipse/org.eclipse.wst.common.component') into project.file('.settings/') + expand(deployname: project.name) outputs.upToDateWhen { false } } -tasks["eclipseJdt"].dependsOn(eclipseJdtPrepare) -tasks["cleanEclipse"].dependsOn(cleanEclipseJdtUi) -tasks["eclipse"].dependsOn(eclipseSettings, eclipseWstComponent) +task cleanEclipseSettings(type: Delete) { + delete project.file('.settings/org.eclipse.jdt.core.prefs') + delete project.file('.settings/org.eclipse.jdt.ui.prefs') + delete project.file('.settings/org.eclipse.wst.common.component') + delete project.file('.settings/org.eclipse.wst.common.project.facet.core.xml') +} + +tasks['eclipse'].dependsOn(eclipseSettings, eclipseJdtSettings, eclipseWstComponentSettings) +tasks['eclipseJdt'].dependsOn(eclipseJdtSettings) +tasks['cleanEclipse'].dependsOn(cleanEclipseSettings) diff --git a/gradle/spring-module.gradle b/gradle/spring-module.gradle index e0faef367adb..7628127cb5d4 100644 --- a/gradle/spring-module.gradle +++ b/gradle/spring-module.gradle @@ -8,15 +8,19 @@ apply plugin: 'me.champeau.jmh' apply from: "$rootDir/gradle/publications.gradle" dependencies { - jmh 'org.openjdk.jmh:jmh-core:1.28' - jmh 'org.openjdk.jmh:jmh-generator-annprocess:1.28' - jmh 'net.sf.jopt-simple:jopt-simple:4.6' + jmh 'org.openjdk.jmh:jmh-core:1.32' + jmh 'org.openjdk.jmh:jmh-generator-annprocess:1.32' + jmh 'net.sf.jopt-simple:jopt-simple' } jmh { duplicateClassesStrategy = DuplicatesStrategy.EXCLUDE } +tasks.findByName("processJmhResources").configure { + duplicatesStrategy = DuplicatesStrategy.EXCLUDE +} + jmhJar { // Uncomment the following for Shadow's Transformer support. // mergeServiceFiles() diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e708b1c023ec..7454180f2ae8 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 442d9132ea32..ffed3a254e91 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 4f906e0c811f..1b6c787337ff 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,67 +17,101 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# 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 +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # 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 +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${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='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # 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 - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 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" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + 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 @@ -106,80 +140,95 @@ 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 +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac 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 +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; 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 +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # 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\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg 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; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# -# 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" +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/integration-tests/integration-tests.gradle b/integration-tests/integration-tests.gradle index 71e23b906049..f7408e5c6ec4 100644 --- a/integration-tests/integration-tests.gradle +++ b/integration-tests/integration-tests.gradle @@ -1,26 +1,26 @@ description = "Spring Integration Tests" dependencies { - testCompile(project(":spring-aop")) - testCompile(project(":spring-beans")) - testCompile(project(":spring-context")) - testCompile(project(":spring-core")) - testCompile(testFixtures(project(":spring-aop"))) - testCompile(testFixtures(project(":spring-beans"))) - testCompile(testFixtures(project(":spring-core"))) - testCompile(testFixtures(project(":spring-tx"))) - testCompile(project(":spring-expression")) - testCompile(project(":spring-jdbc")) - testCompile(project(":spring-orm")) - testCompile(project(":spring-test")) - testCompile(project(":spring-tx")) - testCompile(project(":spring-web")) - testCompile("javax.inject:javax.inject") - testCompile("javax.resource:javax.resource-api") - testCompile("javax.servlet:javax.servlet-api") - testCompile("org.aspectj:aspectjweaver") - testCompile("org.hsqldb:hsqldb") - testCompile("org.hibernate:hibernate-core") + testImplementation(project(":spring-aop")) + testImplementation(project(":spring-beans")) + testImplementation(project(":spring-context")) + testImplementation(project(":spring-core")) + testImplementation(testFixtures(project(":spring-aop"))) + testImplementation(testFixtures(project(":spring-beans"))) + testImplementation(testFixtures(project(":spring-core"))) + testImplementation(testFixtures(project(":spring-tx"))) + testImplementation(project(":spring-expression")) + testImplementation(project(":spring-jdbc")) + testImplementation(project(":spring-orm")) + testImplementation(project(":spring-test")) + testImplementation(project(":spring-tx")) + testImplementation(project(":spring-web")) + testImplementation("javax.inject:javax.inject") + testImplementation("javax.resource:javax.resource-api") + testImplementation("javax.servlet:javax.servlet-api") + testImplementation("org.aspectj:aspectjweaver") + testImplementation("org.hsqldb:hsqldb") + testImplementation("org.hibernate:hibernate-core") } normalization { diff --git a/settings.gradle b/settings.gradle index 6c2fb1952c6b..811aa851d64e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,7 +1,7 @@ pluginManagement { repositories { gradlePluginPortal() - maven { url 'https://repo.spring.io/plugins-release' } + maven { url "https://repo.spring.io/plugins-release" } } } @@ -17,8 +17,6 @@ include "spring-context" include "spring-context-indexer" include "spring-context-support" include "spring-core" -include "kotlin-coroutines" -project(':kotlin-coroutines').projectDir = file('spring-core/kotlin-coroutines') include "spring-expression" include "spring-instrument" include "spring-jcl" @@ -51,7 +49,7 @@ settings.gradle.projectsLoaded { buildScanPublished { scan -> if (buildDir.exists()) { new File(buildDir, "build-scan-uri.txt").text = "${scan.buildScanUri}\n" - } + } } } } diff --git a/spring-aop/spring-aop.gradle b/spring-aop/spring-aop.gradle index 73bb378f39a7..67bf95e8dd6c 100644 --- a/spring-aop/spring-aop.gradle +++ b/spring-aop/spring-aop.gradle @@ -1,12 +1,13 @@ description = "Spring AOP" dependencies { - compile(project(":spring-beans")) - compile(project(":spring-core")) + api(project(":spring-beans")) + api(project(":spring-core")) optional("org.aspectj:aspectjweaver") optional("org.apache.commons:commons-pool2") optional("com.jamonapi:jamon") - testCompile(testFixtures(project(":spring-beans"))) - testCompile(testFixtures(project(":spring-core"))) + testImplementation(testFixtures(project(":spring-beans"))) + testImplementation(testFixtures(project(":spring-core"))) + testFixturesImplementation(testFixtures(project(":spring-beans"))) testFixturesImplementation(testFixtures(project(":spring-core"))) } diff --git a/spring-aop/src/main/java/org/aopalliance/intercept/Joinpoint.java b/spring-aop/src/main/java/org/aopalliance/intercept/Joinpoint.java index 780275e9782c..480d9f087cf5 100644 --- a/spring-aop/src/main/java/org/aopalliance/intercept/Joinpoint.java +++ b/spring-aop/src/main/java/org/aopalliance/intercept/Joinpoint.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2021 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. @@ -26,7 +26,7 @@ * terminology). * *

A runtime joinpoint is an event that occurs on a static - * joinpoint (i.e. a location in a the program). For instance, an + * joinpoint (i.e. a location in a program). For instance, an * invocation is the runtime joinpoint on a method (static joinpoint). * The static part of a given joinpoint can be generically retrieved * using the {@link #getStaticPart()} method. diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/AbstractAspectJAdvisorFactory.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/AbstractAspectJAdvisorFactory.java index e76156bf8265..58f3c23b459f 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/AbstractAspectJAdvisorFactory.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/AbstractAspectJAdvisorFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2021 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. @@ -103,10 +103,11 @@ private boolean compiledByAjc(Class clazz) { @Override public void validate(Class aspectClass) throws AopConfigException { // If the parent has the annotation and isn't abstract it's an error - if (aspectClass.getSuperclass().getAnnotation(Aspect.class) != null && - !Modifier.isAbstract(aspectClass.getSuperclass().getModifiers())) { + Class superclass = aspectClass.getSuperclass(); + if (superclass.getAnnotation(Aspect.class) != null && + !Modifier.isAbstract(superclass.getModifiers())) { throw new AopConfigException("[" + aspectClass.getName() + "] cannot extend concrete aspect [" + - aspectClass.getSuperclass().getName() + "]"); + superclass.getName() + "]"); } AjType ajType = AjTypeSystem.getAjType(aspectClass); diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java b/spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java index 5664cf7ffd55..b2b8060b8a6a 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java +++ b/spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java @@ -521,8 +521,8 @@ AdvisedSupport getConfigurationOnlyCopy() { copy.copyFrom(this); copy.targetSource = EmptyTargetSource.forClass(getTargetClass(), getTargetSource().isStatic()); copy.advisorChainFactory = this.advisorChainFactory; - copy.interfaces = this.interfaces; - copy.advisors = this.advisors; + copy.interfaces = new ArrayList<>(this.interfaces); + copy.advisors = new ArrayList<>(this.advisors); return copy; } diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/target/AbstractBeanFactoryBasedTargetSourceCreator.java b/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/target/AbstractBeanFactoryBasedTargetSourceCreator.java index 4fd173f2893e..fcef74b56ef4 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/target/AbstractBeanFactoryBasedTargetSourceCreator.java +++ b/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/target/AbstractBeanFactoryBasedTargetSourceCreator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2021 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. @@ -125,12 +125,8 @@ public final TargetSource getTargetSource(Class beanClass, String beanName) { */ protected DefaultListableBeanFactory getInternalBeanFactoryForBean(String beanName) { synchronized (this.internalBeanFactories) { - DefaultListableBeanFactory internalBeanFactory = this.internalBeanFactories.get(beanName); - if (internalBeanFactory == null) { - internalBeanFactory = buildInternalBeanFactory(this.beanFactory); - this.internalBeanFactories.put(beanName, internalBeanFactory); - } - return internalBeanFactory; + return this.internalBeanFactories.computeIfAbsent(beanName, + name -> buildInternalBeanFactory(this.beanFactory)); } } diff --git a/spring-aspects/spring-aspects.gradle b/spring-aspects/spring-aspects.gradle index 12adbfb7e5f4..4ee0ef3fda68 100644 --- a/spring-aspects/spring-aspects.gradle +++ b/spring-aspects/spring-aspects.gradle @@ -11,7 +11,7 @@ sourceSets.test.java.srcDirs = files() aspectj.version = dependencyManagement.managedVersions['org.aspectj:aspectjweaver'] dependencies { - compile("org.aspectj:aspectjweaver") + api("org.aspectj:aspectjweaver") compileOnly("org.aspectj:aspectjrt") optional(project(":spring-aop")) // for @Async support optional(project(":spring-beans")) // for @Configurable support @@ -21,13 +21,13 @@ dependencies { optional(project(":spring-tx")) // for JPA, @Transactional support optional("javax.cache:cache-api") // for JCache aspect optional("javax.transaction:javax.transaction-api") // for @javax.transaction.Transactional support - testCompile(project(":spring-core")) // for CodeStyleAspect - testCompile(project(":spring-test")) - testCompile(testFixtures(project(":spring-context"))) - testCompile(testFixtures(project(":spring-context-support"))) - testCompile(testFixtures(project(":spring-core"))) - testCompile(testFixtures(project(":spring-tx"))) - testCompile("javax.mail:javax.mail-api") + testImplementation(project(":spring-core")) // for CodeStyleAspect + testImplementation(project(":spring-test")) + testImplementation(testFixtures(project(":spring-context"))) + testImplementation(testFixtures(project(":spring-context-support"))) + testImplementation(testFixtures(project(":spring-core"))) + testImplementation(testFixtures(project(":spring-tx"))) + testImplementation("javax.mail:javax.mail-api") testCompileOnly("org.aspectj:aspectjrt") } diff --git a/spring-beans/spring-beans.gradle b/spring-beans/spring-beans.gradle index db894e8b83bc..e3f6f73b763b 100644 --- a/spring-beans/spring-beans.gradle +++ b/spring-beans/spring-beans.gradle @@ -4,14 +4,14 @@ apply plugin: "groovy" apply plugin: "kotlin" dependencies { - compile(project(":spring-core")) + api(project(":spring-core")) optional("javax.inject:javax.inject") optional("org.yaml:snakeyaml") optional("org.codehaus.groovy:groovy-xml") optional("org.jetbrains.kotlin:kotlin-reflect") optional("org.jetbrains.kotlin:kotlin-stdlib") - testCompile(testFixtures(project(":spring-core"))) - testCompile("javax.annotation:javax.annotation-api") + testImplementation(testFixtures(project(":spring-core"))) + testImplementation("javax.annotation:javax.annotation-api") testFixturesApi("org.junit.jupiter:junit-jupiter-api") testFixturesImplementation("org.assertj:assertj-core") } diff --git a/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java b/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java index 6e97683f889a..8ddd6ff74467 100644 --- a/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java +++ b/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java @@ -87,7 +87,10 @@ public abstract class BeanUtils { values.put(byte.class, (byte) 0); values.put(short.class, (short) 0); values.put(int.class, 0); - values.put(long.class, (long) 0); + values.put(long.class, 0L); + values.put(float.class, 0F); + values.put(double.class, 0D); + values.put(char.class, '\0'); DEFAULT_TYPE_VALUES = Collections.unmodifiableMap(values); } diff --git a/spring-beans/src/main/java/org/springframework/beans/GenericTypeAwarePropertyDescriptor.java b/spring-beans/src/main/java/org/springframework/beans/GenericTypeAwarePropertyDescriptor.java index 603f5aae150e..b4052b7b84e9 100644 --- a/spring-beans/src/main/java/org/springframework/beans/GenericTypeAwarePropertyDescriptor.java +++ b/spring-beans/src/main/java/org/springframework/beans/GenericTypeAwarePropertyDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -138,7 +138,7 @@ public Method getWriteMethodForActualAccess() { Set ambiguousCandidates = this.ambiguousWriteMethods; if (ambiguousCandidates != null) { this.ambiguousWriteMethods = null; - LogFactory.getLog(GenericTypeAwarePropertyDescriptor.class).warn("Invalid JavaBean property '" + + LogFactory.getLog(GenericTypeAwarePropertyDescriptor.class).debug("Non-unique JavaBean property '" + getName() + "' being accessed! Ambiguous write methods found next to actually used [" + this.writeMethod + "]: " + ambiguousCandidates); } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/ConstructorArgumentValues.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/ConstructorArgumentValues.java index 4fbfb435875d..c4d779e697b8 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/config/ConstructorArgumentValues.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/ConstructorArgumentValues.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -351,7 +351,9 @@ public ValueHolder getArgumentValue(int index, Class requiredType, String req * @return the ValueHolder for the argument, or {@code null} if none set */ @Nullable - public ValueHolder getArgumentValue(int index, @Nullable Class requiredType, @Nullable String requiredName, @Nullable Set usedValueHolders) { + public ValueHolder getArgumentValue(int index, @Nullable Class requiredType, + @Nullable String requiredName, @Nullable Set usedValueHolders) { + Assert.isTrue(index >= 0, "Index must not be negative"); ValueHolder valueHolder = getIndexedArgumentValue(index, requiredType, requiredName); if (valueHolder == null) { diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java index ff76dcdd3710..02b27fe30443 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java @@ -246,6 +246,15 @@ public void setAllowCircularReferences(boolean allowCircularReferences) { this.allowCircularReferences = allowCircularReferences; } + /** + * Return whether to allow circular references between beans. + * @since 5.3.10 + * @see #setAllowCircularReferences + */ + public boolean isAllowCircularReferences() { + return this.allowCircularReferences; + } + /** * Set whether to allow the raw injection of a bean instance into some other * bean's property, despite the injected bean eventually getting wrapped @@ -264,6 +273,15 @@ public void setAllowRawInjectionDespiteWrapping(boolean allowRawInjectionDespite this.allowRawInjectionDespiteWrapping = allowRawInjectionDespiteWrapping; } + /** + * Return whether to allow the raw injection of a bean instance. + * @since 5.3.10 + * @see #setAllowRawInjectionDespiteWrapping + */ + public boolean isAllowRawInjectionDespiteWrapping() { + return this.allowRawInjectionDespiteWrapping; + } + /** * Ignore the given dependency type for autowiring: * for example, String. Default is none. diff --git a/spring-beans/src/test/java/org/springframework/beans/AbstractPropertyAccessorTests.java b/spring-beans/src/test/java/org/springframework/beans/AbstractPropertyAccessorTests.java index 0bb5febde05f..2dd52740b6ae 100644 --- a/spring-beans/src/test/java/org/springframework/beans/AbstractPropertyAccessorTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/AbstractPropertyAccessorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -68,25 +68,25 @@ * @author Dave Syer * @author Stephane Nicoll */ -public abstract class AbstractPropertyAccessorTests { +abstract class AbstractPropertyAccessorTests { protected abstract AbstractPropertyAccessor createAccessor(Object target); @Test - public void createWithNullTarget() { + void createWithNullTarget() { assertThatIllegalArgumentException().isThrownBy(() -> createAccessor(null)); } @Test - public void isReadableProperty() { + void isReadableProperty() { AbstractPropertyAccessor accessor = createAccessor(new Simple("John", 2)); assertThat(accessor.isReadableProperty("name")).isTrue(); } @Test - public void isReadablePropertyNotReadable() { + void isReadablePropertyNotReadable() { AbstractPropertyAccessor accessor = createAccessor(new NoRead()); assertThat(accessor.isReadableProperty("age")).isFalse(); @@ -96,42 +96,42 @@ public void isReadablePropertyNotReadable() { * Shouldn't throw an exception: should just return false */ @Test - public void isReadablePropertyNoSuchProperty() { + void isReadablePropertyNoSuchProperty() { AbstractPropertyAccessor accessor = createAccessor(new NoRead()); assertThat(accessor.isReadableProperty("xxxxx")).isFalse(); } @Test - public void isReadablePropertyNull() { + void isReadablePropertyNull() { AbstractPropertyAccessor accessor = createAccessor(new NoRead()); assertThatIllegalArgumentException().isThrownBy(() -> accessor.isReadableProperty(null)); } @Test - public void isWritableProperty() { + void isWritableProperty() { AbstractPropertyAccessor accessor = createAccessor(new Simple("John", 2)); assertThat(accessor.isWritableProperty("name")).isTrue(); } @Test - public void isWritablePropertyNull() { + void isWritablePropertyNull() { AbstractPropertyAccessor accessor = createAccessor(new NoRead()); assertThatIllegalArgumentException().isThrownBy(() -> accessor.isWritableProperty(null)); } @Test - public void isWritablePropertyNoSuchProperty() { + void isWritablePropertyNoSuchProperty() { AbstractPropertyAccessor accessor = createAccessor(new NoRead()); assertThat(accessor.isWritableProperty("xxxxx")).isFalse(); } @Test - public void isReadableWritableForIndexedProperties() { + void isReadableWritableForIndexedProperties() { IndexedTestBean target = new IndexedTestBean(); AbstractPropertyAccessor accessor = createAccessor(target); @@ -177,28 +177,28 @@ public void isReadableWritableForIndexedProperties() { } @Test - public void getSimpleProperty() { + void getSimpleProperty() { Simple target = new Simple("John", 2); AbstractPropertyAccessor accessor = createAccessor(target); assertThat(accessor.getPropertyValue("name")).isEqualTo("John"); } @Test - public void getNestedProperty() { + void getNestedProperty() { Person target = createPerson("John", "London", "UK"); AbstractPropertyAccessor accessor = createAccessor(target); assertThat(accessor.getPropertyValue("address.city")).isEqualTo("London"); } @Test - public void getNestedDeepProperty() { + void getNestedDeepProperty() { Person target = createPerson("John", "London", "UK"); AbstractPropertyAccessor accessor = createAccessor(target); assertThat(accessor.getPropertyValue("address.country.name")).isEqualTo("UK"); } @Test - public void getAnotherNestedDeepProperty() { + void getAnotherNestedDeepProperty() { ITestBean target = new TestBean("rod", 31); ITestBean kerry = new TestBean("kerry", 35); target.setSpouse(kerry); @@ -213,7 +213,7 @@ public void getAnotherNestedDeepProperty() { } @Test - public void getPropertyIntermediatePropertyIsNull() { + void getPropertyIntermediatePropertyIsNull() { Person target = createPerson("John", "London", "UK"); target.address = null; AbstractPropertyAccessor accessor = createAccessor(target); @@ -226,7 +226,7 @@ public void getPropertyIntermediatePropertyIsNull() { } @Test - public void getPropertyIntermediatePropertyIsNullWithAutoGrow() { + void getPropertyIntermediatePropertyIsNullWithAutoGrow() { Person target = createPerson("John", "London", "UK"); target.address = null; AbstractPropertyAccessor accessor = createAccessor(target); @@ -236,7 +236,7 @@ public void getPropertyIntermediatePropertyIsNullWithAutoGrow() { } @Test - public void getPropertyIntermediateMapEntryIsNullWithAutoGrow() { + void getPropertyIntermediateMapEntryIsNullWithAutoGrow() { Foo target = new Foo(); AbstractPropertyAccessor accessor = createAccessor(target); accessor.setConversionService(new DefaultConversionService()); @@ -246,7 +246,7 @@ public void getPropertyIntermediateMapEntryIsNullWithAutoGrow() { } @Test - public void getUnknownProperty() { + void getUnknownProperty() { Simple target = new Simple("John", 2); AbstractPropertyAccessor accessor = createAccessor(target); assertThatExceptionOfType(NotReadablePropertyException.class).isThrownBy(() -> @@ -258,7 +258,7 @@ public void getUnknownProperty() { } @Test - public void getUnknownNestedProperty() { + void getUnknownNestedProperty() { Person target = createPerson("John", "London", "UK"); AbstractPropertyAccessor accessor = createAccessor(target); @@ -267,7 +267,7 @@ public void getUnknownNestedProperty() { } @Test - public void setSimpleProperty() { + void setSimpleProperty() { Simple target = new Simple("John", 2); AbstractPropertyAccessor accessor = createAccessor(target); @@ -278,7 +278,7 @@ public void setSimpleProperty() { } @Test - public void setNestedProperty() { + void setNestedProperty() { Person target = createPerson("John", "Paris", "FR"); AbstractPropertyAccessor accessor = createAccessor(target); @@ -287,7 +287,7 @@ public void setNestedProperty() { } @Test - public void setNestedPropertyPolymorphic() throws Exception { + void setNestedPropertyPolymorphic() throws Exception { ITestBean target = new TestBean("rod", 31); ITestBean kerry = new Employee(); @@ -296,10 +296,10 @@ public void setNestedPropertyPolymorphic() throws Exception { accessor.setPropertyValue("spouse.age", 35); accessor.setPropertyValue("spouse.name", "Kerry"); accessor.setPropertyValue("spouse.company", "Lewisham"); - assertThat(kerry.getName().equals("Kerry")).as("kerry name is Kerry").isTrue(); + assertThat(kerry.getName()).as("kerry name is Kerry").isEqualTo("Kerry"); assertThat(target.getSpouse() == kerry).as("nested set worked").isTrue(); - assertThat(kerry.getSpouse() == null).as("no back relation").isTrue(); + assertThat(kerry.getSpouse()).as("no back relation").isNull(); accessor.setPropertyValue(new PropertyValue("spouse.spouse", target)); assertThat(kerry.getSpouse() == target).as("nested set worked").isTrue(); @@ -308,7 +308,7 @@ public void setNestedPropertyPolymorphic() throws Exception { } @Test - public void setAnotherNestedProperty() throws Exception { + void setAnotherNestedProperty() throws Exception { ITestBean target = new TestBean("rod", 31); ITestBean kerry = new TestBean("kerry", 0); @@ -316,7 +316,7 @@ public void setAnotherNestedProperty() throws Exception { accessor.setPropertyValue("spouse", kerry); assertThat(target.getSpouse() == kerry).as("nested set worked").isTrue(); - assertThat(kerry.getSpouse() == null).as("no back relation").isTrue(); + assertThat(kerry.getSpouse()).as("no back relation").isNull(); accessor.setPropertyValue(new PropertyValue("spouse.spouse", target)); assertThat(kerry.getSpouse() == target).as("nested set worked").isTrue(); assertThat(kerry.getAge() == 0).as("kerry age not set").isTrue(); @@ -328,7 +328,7 @@ public void setAnotherNestedProperty() throws Exception { } @Test - public void setYetAnotherNestedProperties() { + void setYetAnotherNestedProperties() { String doctorCompany = ""; String lawyerCompany = "Dr. Sueem"; TestBean target = new TestBean(); @@ -340,7 +340,7 @@ public void setYetAnotherNestedProperties() { } @Test - public void setNestedDeepProperty() { + void setNestedDeepProperty() { Person target = createPerson("John", "Paris", "FR"); AbstractPropertyAccessor accessor = createAccessor(target); @@ -349,7 +349,7 @@ public void setNestedDeepProperty() { } @Test - public void testErrorMessageOfNestedProperty() { + void testErrorMessageOfNestedProperty() { ITestBean target = new TestBean(); ITestBean child = new DifferentTestBean(); child.setName("test"); @@ -364,7 +364,7 @@ public void testErrorMessageOfNestedProperty() { } @Test - public void setPropertyIntermediatePropertyIsNull() { + void setPropertyIntermediatePropertyIsNull() { Person target = createPerson("John", "Paris", "FR"); target.address.country = null; AbstractPropertyAccessor accessor = createAccessor(target); @@ -378,7 +378,7 @@ public void setPropertyIntermediatePropertyIsNull() { } @Test - public void setAnotherPropertyIntermediatePropertyIsNull() throws Exception { + void setAnotherPropertyIntermediatePropertyIsNull() throws Exception { ITestBean target = new TestBean("rod", 31); AbstractPropertyAccessor accessor = createAccessor(target); assertThatExceptionOfType(NullValueInNestedPathException.class).isThrownBy(() -> @@ -387,7 +387,7 @@ public void setAnotherPropertyIntermediatePropertyIsNull() throws Exception { } @Test - public void setPropertyIntermediatePropertyIsNullWithAutoGrow() { + void setPropertyIntermediatePropertyIsNullWithAutoGrow() { Person target = createPerson("John", "Paris", "FR"); target.address.country = null; AbstractPropertyAccessor accessor = createAccessor(target); @@ -398,7 +398,7 @@ public void setPropertyIntermediatePropertyIsNullWithAutoGrow() { } @Test - public void setPropertyIntermediateListIsNullWithAutoGrow() { + void setPropertyIntermediateListIsNullWithAutoGrow() { Foo target = new Foo(); AbstractPropertyAccessor accessor = createAccessor(target); accessor.setConversionService(new DefaultConversionService()); @@ -410,7 +410,7 @@ public void setPropertyIntermediateListIsNullWithAutoGrow() { } @Test - public void setPropertyIntermediateListIsNullWithNoConversionService() { + void setPropertyIntermediateListIsNullWithNoConversionService() { Foo target = new Foo(); AbstractPropertyAccessor accessor = createAccessor(target); accessor.setAutoGrowNestedPaths(true); @@ -419,7 +419,7 @@ public void setPropertyIntermediateListIsNullWithNoConversionService() { } @Test - public void setPropertyIntermediateListIsNullWithBadConversionService() { + void setPropertyIntermediateListIsNullWithBadConversionService() { Foo target = new Foo(); AbstractPropertyAccessor accessor = createAccessor(target); accessor.setConversionService(new GenericConversionService() { @@ -435,7 +435,7 @@ public Object convert(@Nullable Object source, @Nullable TypeDescriptor sourceTy @Test - public void setEmptyPropertyValues() { + void setEmptyPropertyValues() { TestBean target = new TestBean(); int age = 50; String name = "Tony"; @@ -452,7 +452,7 @@ public void setEmptyPropertyValues() { @Test - public void setValidPropertyValues() { + void setValidPropertyValues() { TestBean target = new TestBean(); String newName = "tony"; int newAge = 65; @@ -469,7 +469,7 @@ public void setValidPropertyValues() { } @Test - public void setIndividualValidPropertyValues() { + void setIndividualValidPropertyValues() { TestBean target = new TestBean(); String newName = "tony"; int newAge = 65; @@ -478,39 +478,39 @@ public void setIndividualValidPropertyValues() { accessor.setPropertyValue("age", newAge); accessor.setPropertyValue(new PropertyValue("name", newName)); accessor.setPropertyValue(new PropertyValue("touchy", newTouchy)); - assertThat(target.getName().equals(newName)).as("Name property should have changed").isTrue(); - assertThat(target.getTouchy().equals(newTouchy)).as("Touchy property should have changed").isTrue(); + assertThat(target.getName()).as("Name property should have changed").isEqualTo(newName); + assertThat(target.getTouchy()).as("Touchy property should have changed").isEqualTo(newTouchy); assertThat(target.getAge() == newAge).as("Age property should have changed").isTrue(); } @Test - public void setPropertyIsReflectedImmediately() { + void setPropertyIsReflectedImmediately() { TestBean target = new TestBean(); int newAge = 33; AbstractPropertyAccessor accessor = createAccessor(target); target.setAge(newAge); Object bwAge = accessor.getPropertyValue("age"); - assertThat(bwAge instanceof Integer).as("Age is an integer").isTrue(); + assertThat(bwAge).as("Age is an integer").isInstanceOf(Integer.class); assertThat(bwAge).as("Bean wrapper must pick up changes").isEqualTo(newAge); } @Test - public void setPropertyToNull() { + void setPropertyToNull() { TestBean target = new TestBean(); target.setName("Frank"); // we need to change it back target.setSpouse(target); AbstractPropertyAccessor accessor = createAccessor(target); - assertThat(target.getName() != null).as("name is not null to start off").isTrue(); + assertThat(target.getName()).as("name is not null to start off").isNotNull(); accessor.setPropertyValue("name", null); - assertThat(target.getName() == null).as("name is now null").isTrue(); + assertThat(target.getName()).as("name is now null").isNull(); // now test with non-string - assertThat(target.getSpouse() != null).as("spouse is not null to start off").isTrue(); + assertThat(target.getSpouse()).as("spouse is not null to start off").isNotNull(); accessor.setPropertyValue("spouse", null); - assertThat(target.getSpouse() == null).as("spouse is now null").isTrue(); + assertThat(target.getSpouse()).as("spouse is now null").isNull(); } @Test - public void setIndexedPropertyIgnored() { + void setIndexedPropertyIgnored() { MutablePropertyValues values = new MutablePropertyValues(); values.add("toBeIgnored[0]", 42); AbstractPropertyAccessor accessor = createAccessor(new Object()); @@ -518,7 +518,7 @@ public void setIndexedPropertyIgnored() { } @Test - public void setPropertyWithPrimitiveConversion() { + void setPropertyWithPrimitiveConversion() { MutablePropertyValues values = new MutablePropertyValues(); values.add("name", 42); TestBean target = new TestBean(); @@ -528,7 +528,7 @@ public void setPropertyWithPrimitiveConversion() { } @Test - public void setPropertyWithCustomEditor() { + void setPropertyWithCustomEditor() { MutablePropertyValues values = new MutablePropertyValues(); values.add("name", Integer.class); TestBean target = new TestBean(); @@ -544,7 +544,7 @@ public void setValue(Object value) { } @Test - public void setStringPropertyWithCustomEditor() throws Exception { + void setStringPropertyWithCustomEditor() throws Exception { TestBean target = new TestBean(); AbstractPropertyAccessor accessor = createAccessor(target); accessor.registerCustomEditor(String.class, "name", new PropertyEditorSupport() { @@ -567,7 +567,7 @@ public void setValue(Object value) { } @Test - public void setBooleanProperty() { + void setBooleanProperty() { BooleanTestBean target = new BooleanTestBean(); AbstractPropertyAccessor accessor = createAccessor(target); @@ -581,7 +581,7 @@ public void setBooleanProperty() { } @Test - public void setNumberProperties() { + void setNumberProperties() { NumberTestBean target = new NumberTestBean(); AbstractPropertyAccessor accessor = createAccessor(target); accessor.setPropertyValue("short2", "2"); @@ -591,24 +591,24 @@ public void setNumberProperties() { accessor.setPropertyValue("float2", "8.1"); accessor.setPropertyValue("double2", "6.1"); accessor.setPropertyValue("bigDecimal", "4.0"); - assertThat(new Short("2").equals(accessor.getPropertyValue("short2"))).as("Correct short2 value").isTrue(); - assertThat(new Short("2").equals(target.getShort2())).as("Correct short2 value").isTrue(); - assertThat(new Integer("8").equals(accessor.getPropertyValue("int2"))).as("Correct int2 value").isTrue(); - assertThat(new Integer("8").equals(target.getInt2())).as("Correct int2 value").isTrue(); - assertThat(new Long("6").equals(accessor.getPropertyValue("long2"))).as("Correct long2 value").isTrue(); - assertThat(new Long("6").equals(target.getLong2())).as("Correct long2 value").isTrue(); - assertThat(new BigInteger("3").equals(accessor.getPropertyValue("bigInteger"))).as("Correct bigInteger value").isTrue(); - assertThat(new BigInteger("3").equals(target.getBigInteger())).as("Correct bigInteger value").isTrue(); - assertThat(new Float("8.1").equals(accessor.getPropertyValue("float2"))).as("Correct float2 value").isTrue(); - assertThat(new Float("8.1").equals(target.getFloat2())).as("Correct float2 value").isTrue(); - assertThat(new Double("6.1").equals(accessor.getPropertyValue("double2"))).as("Correct double2 value").isTrue(); - assertThat(new Double("6.1").equals(target.getDouble2())).as("Correct double2 value").isTrue(); - assertThat(new BigDecimal("4.0").equals(accessor.getPropertyValue("bigDecimal"))).as("Correct bigDecimal value").isTrue(); - assertThat(new BigDecimal("4.0").equals(target.getBigDecimal())).as("Correct bigDecimal value").isTrue(); - } - - @Test - public void setNumberPropertiesWithCoercion() { + assertThat(Short.valueOf("2")).as("Correct short2 value").isEqualTo(accessor.getPropertyValue("short2")); + assertThat(Short.valueOf("2")).as("Correct short2 value").isEqualTo(target.getShort2()); + assertThat(Integer.valueOf("8")).as("Correct int2 value").isEqualTo(accessor.getPropertyValue("int2")); + assertThat(Integer.valueOf("8")).as("Correct int2 value").isEqualTo(target.getInt2()); + assertThat(Long.valueOf("6")).as("Correct long2 value").isEqualTo(accessor.getPropertyValue("long2")); + assertThat(Long.valueOf("6")).as("Correct long2 value").isEqualTo(target.getLong2()); + assertThat(new BigInteger("3")).as("Correct bigInteger value").isEqualTo(accessor.getPropertyValue("bigInteger")); + assertThat(new BigInteger("3")).as("Correct bigInteger value").isEqualTo(target.getBigInteger()); + assertThat(Float.valueOf("8.1")).as("Correct float2 value").isEqualTo(accessor.getPropertyValue("float2")); + assertThat(Float.valueOf("8.1")).as("Correct float2 value").isEqualTo(target.getFloat2()); + assertThat(Double.valueOf("6.1").equals(accessor.getPropertyValue("double2"))).as("Correct double2 value").isTrue(); + assertThat(Double.valueOf("6.1")).as("Correct double2 value").isEqualTo(target.getDouble2()); + assertThat(new BigDecimal("4.0")).as("Correct bigDecimal value").isEqualTo(accessor.getPropertyValue("bigDecimal")); + assertThat(new BigDecimal("4.0")).as("Correct bigDecimal value").isEqualTo(target.getBigDecimal()); + } + + @Test + void setNumberPropertiesWithCoercion() { NumberTestBean target = new NumberTestBean(); AbstractPropertyAccessor accessor = createAccessor(target); accessor.setPropertyValue("short2", 2); @@ -616,26 +616,26 @@ public void setNumberPropertiesWithCoercion() { accessor.setPropertyValue("long2", new BigInteger("6")); accessor.setPropertyValue("bigInteger", 3L); accessor.setPropertyValue("float2", 8.1D); - accessor.setPropertyValue("double2", new BigDecimal(6.1)); + accessor.setPropertyValue("double2", new BigDecimal("6.1")); accessor.setPropertyValue("bigDecimal", 4.0F); - assertThat(new Short("2").equals(accessor.getPropertyValue("short2"))).as("Correct short2 value").isTrue(); - assertThat(new Short("2").equals(target.getShort2())).as("Correct short2 value").isTrue(); - assertThat(new Integer("8").equals(accessor.getPropertyValue("int2"))).as("Correct int2 value").isTrue(); - assertThat(new Integer("8").equals(target.getInt2())).as("Correct int2 value").isTrue(); - assertThat(new Long("6").equals(accessor.getPropertyValue("long2"))).as("Correct long2 value").isTrue(); - assertThat(new Long("6").equals(target.getLong2())).as("Correct long2 value").isTrue(); + assertThat(Short.valueOf("2")).as("Correct short2 value").isEqualTo(accessor.getPropertyValue("short2")); + assertThat(Short.valueOf("2")).as("Correct short2 value").isEqualTo(target.getShort2()); + assertThat(Integer.valueOf("8")).as("Correct int2 value").isEqualTo(accessor.getPropertyValue("int2")); + assertThat(Integer.valueOf("8")).as("Correct int2 value").isEqualTo(target.getInt2()); + assertThat(Long.valueOf("6")).as("Correct long2 value").isEqualTo(accessor.getPropertyValue("long2")); + assertThat(Long.valueOf("6")).as("Correct long2 value").isEqualTo(target.getLong2()); assertThat(new BigInteger("3").equals(accessor.getPropertyValue("bigInteger"))).as("Correct bigInteger value").isTrue(); - assertThat(new BigInteger("3").equals(target.getBigInteger())).as("Correct bigInteger value").isTrue(); - assertThat(new Float("8.1").equals(accessor.getPropertyValue("float2"))).as("Correct float2 value").isTrue(); - assertThat(new Float("8.1").equals(target.getFloat2())).as("Correct float2 value").isTrue(); - assertThat(new Double("6.1").equals(accessor.getPropertyValue("double2"))).as("Correct double2 value").isTrue(); - assertThat(new Double("6.1").equals(target.getDouble2())).as("Correct double2 value").isTrue(); - assertThat(new BigDecimal("4.0").equals(accessor.getPropertyValue("bigDecimal"))).as("Correct bigDecimal value").isTrue(); - assertThat(new BigDecimal("4.0").equals(target.getBigDecimal())).as("Correct bigDecimal value").isTrue(); + assertThat(new BigInteger("3")).as("Correct bigInteger value").isEqualTo(target.getBigInteger()); + assertThat(Float.valueOf("8.1")).as("Correct float2 value").isEqualTo(accessor.getPropertyValue("float2")); + assertThat(Float.valueOf("8.1")).as("Correct float2 value").isEqualTo(target.getFloat2()); + assertThat(Double.valueOf("6.1")).as("Correct double2 value").isEqualTo(accessor.getPropertyValue("double2")); + assertThat(Double.valueOf("6.1")).as("Correct double2 value").isEqualTo(target.getDouble2()); + assertThat(new BigDecimal("4.0")).as("Correct bigDecimal value").isEqualTo(accessor.getPropertyValue("bigDecimal")); + assertThat(new BigDecimal("4.0")).as("Correct bigDecimal value").isEqualTo(target.getBigDecimal()); } @Test - public void setPrimitiveProperties() { + void setPrimitiveProperties() { NumberPropertyBean target = new NumberPropertyBean(); AbstractPropertyAccessor accessor = createAccessor(target); @@ -684,7 +684,7 @@ public void setPrimitiveProperties() { } @Test - public void setEnumProperty() { + void setEnumProperty() { EnumTester target = new EnumTester(); AbstractPropertyAccessor accessor = createAccessor(target); @@ -699,7 +699,7 @@ public void setEnumProperty() { } @Test - public void setGenericEnumProperty() { + void setGenericEnumProperty() { EnumConsumer target = new EnumConsumer(); AbstractPropertyAccessor accessor = createAccessor(target); accessor.setPropertyValue("enumValue", TestEnum.class.getName() + ".TEST_VALUE"); @@ -707,7 +707,7 @@ public void setGenericEnumProperty() { } @Test - public void setWildcardEnumProperty() { + void setWildcardEnumProperty() { WildcardEnumConsumer target = new WildcardEnumConsumer(); AbstractPropertyAccessor accessor = createAccessor(target); accessor.setPropertyValue("enumValue", TestEnum.class.getName() + ".TEST_VALUE"); @@ -715,7 +715,7 @@ public void setWildcardEnumProperty() { } @Test - public void setPropertiesProperty() throws Exception { + void setPropertiesProperty() throws Exception { PropsTester target = new PropsTester(); AbstractPropertyAccessor accessor = createAccessor(target); accessor.setPropertyValue("name", "ptest"); @@ -724,53 +724,41 @@ public void setPropertiesProperty() throws Exception { String ps = "peace=war\nfreedom=slavery"; accessor.setPropertyValue("properties", ps); - assertThat(target.name.equals("ptest")).as("name was set").isTrue(); - assertThat(target.properties != null).as("properties non null").isTrue(); + assertThat(target.name).as("name was set").isEqualTo("ptest"); + assertThat(target.properties).as("properties non null").isNotNull(); String freedomVal = target.properties.getProperty("freedom"); String peaceVal = target.properties.getProperty("peace"); - assertThat(peaceVal.equals("war")).as("peace==war").isTrue(); + assertThat(peaceVal).as("peace==war").isEqualTo("war"); assertThat(freedomVal.equals("slavery")).as("Freedom==slavery").isTrue(); } @Test - public void setStringArrayProperty() throws Exception { + void setStringArrayProperty() throws Exception { PropsTester target = new PropsTester(); AbstractPropertyAccessor accessor = createAccessor(target); - accessor.setPropertyValue("stringArray", new String[] {"foo", "fi", "fi", "fum"}); - assertThat(target.stringArray.length == 4).as("stringArray length = 4").isTrue(); - assertThat(target.stringArray[0].equals("foo") && target.stringArray[1].equals("fi") && - target.stringArray[2].equals("fi") && target.stringArray[3].equals("fum")).as("correct values").isTrue(); + accessor.setPropertyValue("stringArray", new String[]{"foo", "fi", "fi", "fum"}); + assertThat(target.stringArray).containsExactly("foo", "fi", "fi", "fum"); - List list = new ArrayList<>(); - list.add("foo"); - list.add("fi"); - list.add("fi"); - list.add("fum"); - accessor.setPropertyValue("stringArray", list); - assertThat(target.stringArray.length == 4).as("stringArray length = 4").isTrue(); - assertThat(target.stringArray[0].equals("foo") && target.stringArray[1].equals("fi") && - target.stringArray[2].equals("fi") && target.stringArray[3].equals("fum")).as("correct values").isTrue(); + accessor.setPropertyValue("stringArray", Arrays.asList("foo", "fi", "fi", "fum")); + assertThat(target.stringArray).containsExactly("foo", "fi", "fi", "fum"); Set set = new HashSet<>(); set.add("foo"); set.add("fi"); set.add("fum"); accessor.setPropertyValue("stringArray", set); - assertThat(target.stringArray.length == 3).as("stringArray length = 3").isTrue(); - List result = Arrays.asList(target.stringArray); - assertThat(result.contains("foo") && result.contains("fi") && result.contains("fum")).as("correct values").isTrue(); + assertThat(target.stringArray).containsExactlyInAnyOrder("foo", "fi", "fum"); accessor.setPropertyValue("stringArray", "one"); - assertThat(target.stringArray.length == 1).as("stringArray length = 1").isTrue(); - assertThat(target.stringArray[0].equals("one")).as("stringArray elt is ok").isTrue(); + assertThat(target.stringArray).containsExactly("one"); accessor.setPropertyValue("stringArray", null); - assertThat(target.stringArray == null).as("stringArray is null").isTrue(); + assertThat(target.stringArray).as("stringArray is null").isNull(); } @Test - public void setStringArrayPropertyWithCustomStringEditor() throws Exception { + void setStringArrayPropertyWithCustomStringEditor() throws Exception { PropsTester target = new PropsTester(); AbstractPropertyAccessor accessor = createAccessor(target); accessor.registerCustomEditor(String.class, "stringArray", new PropertyEditorSupport() { @@ -781,126 +769,90 @@ public void setAsText(String text) { }); accessor.setPropertyValue("stringArray", new String[] {"4foo", "7fi", "6fi", "5fum"}); - assertThat(target.stringArray.length == 4).as("stringArray length = 4").isTrue(); - assertThat(target.stringArray[0].equals("foo") && target.stringArray[1].equals("fi") && - target.stringArray[2].equals("fi") && target.stringArray[3].equals("fum")).as("correct values").isTrue(); + assertThat(target.stringArray).containsExactly("foo", "fi", "fi", "fum"); - List list = new ArrayList<>(); - list.add("4foo"); - list.add("7fi"); - list.add("6fi"); - list.add("5fum"); + List list = Arrays.asList("4foo", "7fi", "6fi", "5fum"); accessor.setPropertyValue("stringArray", list); - assertThat(target.stringArray.length == 4).as("stringArray length = 4").isTrue(); - assertThat(target.stringArray[0].equals("foo") && target.stringArray[1].equals("fi") && - target.stringArray[2].equals("fi") && target.stringArray[3].equals("fum")).as("correct values").isTrue(); + assertThat(target.stringArray).containsExactly("foo", "fi", "fi", "fum"); Set set = new HashSet<>(); set.add("4foo"); set.add("7fi"); set.add("6fum"); accessor.setPropertyValue("stringArray", set); - assertThat(target.stringArray.length == 3).as("stringArray length = 3").isTrue(); - List result = Arrays.asList(target.stringArray); - assertThat(result.contains("foo") && result.contains("fi") && result.contains("fum")).as("correct values").isTrue(); + assertThat(target.stringArray).containsExactlyInAnyOrder("foo", "fi", "fum"); accessor.setPropertyValue("stringArray", "8one"); - assertThat(target.stringArray.length == 1).as("stringArray length = 1").isTrue(); - assertThat(target.stringArray[0].equals("one")).as("correct values").isTrue(); + assertThat(target.stringArray).containsExactly("one"); } @Test - public void setStringArrayPropertyWithStringSplitting() throws Exception { + void setStringArrayPropertyWithStringSplitting() throws Exception { PropsTester target = new PropsTester(); AbstractPropertyAccessor accessor = createAccessor(target); accessor.useConfigValueEditors(); accessor.setPropertyValue("stringArray", "a1,b2"); - assertThat(target.stringArray.length == 2).as("stringArray length = 2").isTrue(); - assertThat(target.stringArray[0].equals("a1") && target.stringArray[1].equals("b2")).as("correct values").isTrue(); + assertThat(target.stringArray).containsExactly("a1", "b2"); } @Test - public void setStringArrayPropertyWithCustomStringDelimiter() throws Exception { + void setStringArrayPropertyWithCustomStringDelimiter() throws Exception { PropsTester target = new PropsTester(); AbstractPropertyAccessor accessor = createAccessor(target); accessor.registerCustomEditor(String[].class, "stringArray", new StringArrayPropertyEditor("-")); accessor.setPropertyValue("stringArray", "a1-b2"); - assertThat(target.stringArray.length == 2).as("stringArray length = 2").isTrue(); - assertThat(target.stringArray[0].equals("a1") && target.stringArray[1].equals("b2")).as("correct values").isTrue(); + assertThat(target.stringArray).containsExactly("a1", "b2"); } @Test - public void setStringArrayWithAutoGrow() throws Exception { + void setStringArrayWithAutoGrow() throws Exception { StringArrayBean target = new StringArrayBean(); AbstractPropertyAccessor accessor = createAccessor(target); accessor.setAutoGrowNestedPaths(true); accessor.setPropertyValue("array[0]", "Test0"); - assertThat(target.getArray().length).isEqualTo(1); + assertThat(target.getArray()).containsExactly("Test0"); accessor.setPropertyValue("array[2]", "Test2"); - assertThat(target.getArray().length).isEqualTo(3); - assertThat(target.getArray()[0].equals("Test0") && target.getArray()[1] == null && - target.getArray()[2].equals("Test2")).as("correct values").isTrue(); + assertThat(target.getArray()).containsExactly("Test0", null, "Test2"); } @Test - public void setIntArrayProperty() { + void setIntArrayProperty() { PropsTester target = new PropsTester(); AbstractPropertyAccessor accessor = createAccessor(target); accessor.setPropertyValue("intArray", new int[] {4, 5, 2, 3}); - assertThat(target.intArray.length == 4).as("intArray length = 4").isTrue(); - assertThat(target.intArray[0] == 4 && target.intArray[1] == 5 && - target.intArray[2] == 2 && target.intArray[3] == 3).as("correct values").isTrue(); + assertThat(target.intArray).containsExactly(4, 5, 2, 3); accessor.setPropertyValue("intArray", new String[] {"4", "5", "2", "3"}); - assertThat(target.intArray.length == 4).as("intArray length = 4").isTrue(); - assertThat(target.intArray[0] == 4 && target.intArray[1] == 5 && - target.intArray[2] == 2 && target.intArray[3] == 3).as("correct values").isTrue(); - - List list = new ArrayList<>(); - list.add(4); - list.add("5"); - list.add(2); - list.add("3"); - accessor.setPropertyValue("intArray", list); - assertThat(target.intArray.length == 4).as("intArray length = 4").isTrue(); - assertThat(target.intArray[0] == 4 && target.intArray[1] == 5 && - target.intArray[2] == 2 && target.intArray[3] == 3).as("correct values").isTrue(); + assertThat(target.intArray).containsExactly(4, 5, 2, 3); + + accessor.setPropertyValue("intArray", Arrays.asList(4, "5", 2, "3")); + assertThat(target.intArray).containsExactly(4, 5, 2, 3); Set set = new HashSet<>(); set.add("4"); set.add(5); set.add("3"); accessor.setPropertyValue("intArray", set); - assertThat(target.intArray.length == 3).as("intArray length = 3").isTrue(); - List result = new ArrayList<>(); - result.add(target.intArray[0]); - result.add(target.intArray[1]); - result.add(target.intArray[2]); - assertThat(result.contains(4) && result.contains(5) && - result.contains(3)).as("correct values").isTrue(); + assertThat(target.intArray).containsExactlyInAnyOrder(4, 5, 3); accessor.setPropertyValue("intArray", new Integer[] {1}); - assertThat(target.intArray.length == 1).as("intArray length = 4").isTrue(); - assertThat(target.intArray[0] == 1).as("correct values").isTrue(); + assertThat(target.intArray).containsExactly(1); accessor.setPropertyValue("intArray", 1); - assertThat(target.intArray.length == 1).as("intArray length = 4").isTrue(); - assertThat(target.intArray[0] == 1).as("correct values").isTrue(); + assertThat(target.intArray).containsExactly(1); accessor.setPropertyValue("intArray", new String[] {"1"}); - assertThat(target.intArray.length == 1).as("intArray length = 4").isTrue(); - assertThat(target.intArray[0] == 1).as("correct values").isTrue(); + assertThat(target.intArray).containsExactly(1); accessor.setPropertyValue("intArray", "1"); - assertThat(target.intArray.length == 1).as("intArray length = 4").isTrue(); - assertThat(target.intArray[0] == 1).as("correct values").isTrue(); + assertThat(target.intArray).containsExactly(1); } @Test - public void setIntArrayPropertyWithCustomEditor() { + void setIntArrayPropertyWithCustomEditor() { PropsTester target = new PropsTester(); AbstractPropertyAccessor accessor = createAccessor(target); accessor.registerCustomEditor(int.class, new PropertyEditorSupport() { @@ -911,50 +863,40 @@ public void setAsText(String text) { }); accessor.setPropertyValue("intArray", new int[] {4, 5, 2, 3}); - assertThat(target.intArray.length == 4).as("intArray length = 4").isTrue(); - assertThat(target.intArray[0] == 4 && target.intArray[1] == 5 && - target.intArray[2] == 2 && target.intArray[3] == 3).as("correct values").isTrue(); + assertThat(target.intArray).containsExactly(4, 5, 2, 3); accessor.setPropertyValue("intArray", new String[] {"3", "4", "1", "2"}); - assertThat(target.intArray.length == 4).as("intArray length = 4").isTrue(); - assertThat(target.intArray[0] == 4 && target.intArray[1] == 5 && - target.intArray[2] == 2 && target.intArray[3] == 3).as("correct values").isTrue(); + assertThat(target.intArray).containsExactly(4, 5, 2, 3); accessor.setPropertyValue("intArray", 1); - assertThat(target.intArray.length == 1).as("intArray length = 4").isTrue(); - assertThat(target.intArray[0] == 1).as("correct values").isTrue(); + assertThat(target.intArray).containsExactly(1); - accessor.setPropertyValue("intArray", new String[] {"0"}); - assertThat(target.intArray.length == 1).as("intArray length = 4").isTrue(); - assertThat(target.intArray[0] == 1).as("correct values").isTrue(); + accessor.setPropertyValue("intArray", new String[]{"0"}); + assertThat(target.intArray).containsExactly(1); accessor.setPropertyValue("intArray", "0"); - assertThat(target.intArray.length == 1).as("intArray length = 4").isTrue(); - assertThat(target.intArray[0] == 1).as("correct values").isTrue(); + assertThat(target.intArray).containsExactly(1); } @Test - public void setIntArrayPropertyWithStringSplitting() throws Exception { + void setIntArrayPropertyWithStringSplitting() throws Exception { PropsTester target = new PropsTester(); AbstractPropertyAccessor accessor = createAccessor(target); accessor.useConfigValueEditors(); accessor.setPropertyValue("intArray", "4,5"); - assertThat(target.intArray.length == 2).as("intArray length = 2").isTrue(); - assertThat(target.intArray[0] == 4 && target.intArray[1] == 5).as("correct values").isTrue(); + assertThat(target.intArray).containsExactly(4, 5); } @Test - public void setPrimitiveArrayProperty() { + void setPrimitiveArrayProperty() { PrimitiveArrayBean target = new PrimitiveArrayBean(); AbstractPropertyAccessor accessor = createAccessor(target); - accessor.setPropertyValue("array", new String[] {"1", "2"}); - assertThat(target.getArray().length).isEqualTo(2); - assertThat(target.getArray()[0]).isEqualTo(1); - assertThat(target.getArray()[1]).isEqualTo(2); + accessor.setPropertyValue("array", new String[]{"1", "2"}); + assertThat(target.getArray()).containsExactly(1, 2); } @Test - public void setPrimitiveArrayPropertyLargeMatchingWithSpecificEditor() { + void setPrimitiveArrayPropertyLargeMatchingWithSpecificEditor() { PrimitiveArrayBean target = new PrimitiveArrayBean(); AbstractPropertyAccessor accessor = createAccessor(target); accessor.registerCustomEditor(int.class, "array", new PropertyEditorSupport() { @@ -965,15 +907,14 @@ public void setValue(Object value) { } } }); - int[] input = new int[1024]; + int[] input = new int[10]; accessor.setPropertyValue("array", input); - assertThat(target.getArray().length).isEqualTo(1024); - assertThat(target.getArray()[0]).isEqualTo(1); - assertThat(target.getArray()[1]).isEqualTo(1); + assertThat(target.getArray()).hasSize(10); + assertThat(Arrays.stream(target.getArray())).allMatch(n -> n == 1); } @Test - public void setPrimitiveArrayPropertyLargeMatchingWithIndexSpecificEditor() { + void setPrimitiveArrayPropertyLargeMatchingWithIndexSpecificEditor() { PrimitiveArrayBean target = new PrimitiveArrayBean(); AbstractPropertyAccessor accessor = createAccessor(target); accessor.registerCustomEditor(int.class, "array[1]", new PropertyEditorSupport() { @@ -984,49 +925,38 @@ public void setValue(Object value) { } } }); - int[] input = new int[1024]; + int[] input = new int[10]; accessor.setPropertyValue("array", input); - assertThat(target.getArray().length).isEqualTo(1024); - assertThat(target.getArray()[0]).isEqualTo(0); + assertThat(target.getArray()).hasSize(10); + assertThat(target.getArray()[0]).isZero(); assertThat(target.getArray()[1]).isEqualTo(1); + assertThat(Arrays.stream(target.getArray()).skip(2)).allMatch(n -> n == 0); } @Test - public void setPrimitiveArrayPropertyWithAutoGrow() throws Exception { + void setPrimitiveArrayPropertyWithAutoGrow() throws Exception { PrimitiveArrayBean target = new PrimitiveArrayBean(); AbstractPropertyAccessor accessor = createAccessor(target); accessor.setAutoGrowNestedPaths(true); accessor.setPropertyValue("array[0]", 1); - assertThat(target.getArray().length).isEqualTo(1); + assertThat(target.getArray()).containsExactly(1); accessor.setPropertyValue("array[2]", 3); - assertThat(target.getArray().length).isEqualTo(3); - assertThat(target.getArray()[0] == 1 && target.getArray()[1] == 0 && - target.getArray()[2] == 3).as("correct values").isTrue(); + assertThat(target.getArray()).containsExactly(1, 0, 3); } @Test - @SuppressWarnings("rawtypes") - public void setGenericArrayProperty() { + void setGenericArrayProperty() { + @SuppressWarnings("rawtypes") SkipReaderStub target = new SkipReaderStub(); AbstractPropertyAccessor accessor = createAccessor(target); - List values = new ArrayList<>(); - values.add("1"); - values.add("2"); - values.add("3"); - values.add("4"); - accessor.setPropertyValue("items", values); - Object[] result = target.items; - assertThat(result.length).isEqualTo(4); - assertThat(result[0]).isEqualTo("1"); - assertThat(result[1]).isEqualTo("2"); - assertThat(result[2]).isEqualTo("3"); - assertThat(result[3]).isEqualTo("4"); + accessor.setPropertyValue("items", Arrays.asList("1", "2", "3", "4")); + assertThat(target.items).containsExactly("1", "2", "3", "4"); } @Test - public void setArrayPropertyToObject() { + void setArrayPropertyToObject() { ArrayToObject target = new ArrayToObject(); AbstractPropertyAccessor accessor = createAccessor(target); @@ -1040,7 +970,7 @@ public void setArrayPropertyToObject() { } @Test - public void setCollectionProperty() { + void setCollectionProperty() { IndexedTestBean target = new IndexedTestBean(); AbstractPropertyAccessor accessor = createAccessor(target); Collection coll = new HashSet<>(); @@ -1061,9 +991,9 @@ public void setCollectionProperty() { assertThat((List) target.getList()).isSameAs(list); } - @SuppressWarnings("unchecked") // list cannot be properly parameterized as it breaks other tests @Test - public void setCollectionPropertyNonMatchingType() { + @SuppressWarnings("unchecked") // list cannot be properly parameterized as it breaks other tests + void setCollectionPropertyNonMatchingType() { IndexedTestBean target = new IndexedTestBean(); AbstractPropertyAccessor accessor = createAccessor(target); Collection coll = new ArrayList<>(); @@ -1078,7 +1008,7 @@ public void setCollectionPropertyNonMatchingType() { Set list = new HashSet<>(); list.add("list1"); accessor.setPropertyValue("list", list); - assertThat(target.getCollection().size()).isEqualTo(1); + assertThat(target.getCollection()).hasSize(1); assertThat(target.getCollection().containsAll(coll)).isTrue(); assertThat(target.getSet().size()).isEqualTo(1); assertThat(target.getSet().containsAll(set)).isTrue(); @@ -1088,9 +1018,9 @@ public void setCollectionPropertyNonMatchingType() { assertThat(target.getList().containsAll(list)).isTrue(); } - @SuppressWarnings("unchecked") // list cannot be properly parameterized as it breaks other tests @Test - public void setCollectionPropertyWithArrayValue() { + @SuppressWarnings("unchecked") // list cannot be properly parameterized as it breaks other tests + void setCollectionPropertyWithArrayValue() { IndexedTestBean target = new IndexedTestBean(); AbstractPropertyAccessor accessor = createAccessor(target); Collection coll = new HashSet<>(); @@ -1105,7 +1035,7 @@ public void setCollectionPropertyWithArrayValue() { Set list = new HashSet<>(); list.add("list1"); accessor.setPropertyValue("list", list.toArray()); - assertThat(target.getCollection().size()).isEqualTo(1); + assertThat(target.getCollection()).hasSize(1); assertThat(target.getCollection().containsAll(coll)).isTrue(); assertThat(target.getSet().size()).isEqualTo(1); assertThat(target.getSet().containsAll(set)).isTrue(); @@ -1115,24 +1045,24 @@ public void setCollectionPropertyWithArrayValue() { assertThat(target.getList().containsAll(list)).isTrue(); } - @SuppressWarnings("unchecked") // list cannot be properly parameterized as it breaks other tests @Test - public void setCollectionPropertyWithIntArrayValue() { + @SuppressWarnings("unchecked") // list cannot be properly parameterized as it breaks other tests + void setCollectionPropertyWithIntArrayValue() { IndexedTestBean target = new IndexedTestBean(); AbstractPropertyAccessor accessor = createAccessor(target); Collection coll = new HashSet<>(); coll.add(0); - accessor.setPropertyValue("collection", new int[] {0}); + accessor.setPropertyValue("collection", new int[]{0}); List set = new ArrayList<>(); set.add(1); - accessor.setPropertyValue("set", new int[] {1}); + accessor.setPropertyValue("set", new int[]{1}); List sortedSet = new ArrayList<>(); sortedSet.add(2); - accessor.setPropertyValue("sortedSet", new int[] {2}); + accessor.setPropertyValue("sortedSet", new int[]{2}); Set list = new HashSet<>(); list.add(3); - accessor.setPropertyValue("list", new int[] {3}); - assertThat(target.getCollection().size()).isEqualTo(1); + accessor.setPropertyValue("list", new int[]{3}); + assertThat(target.getCollection()).hasSize(1); assertThat(target.getCollection().containsAll(coll)).isTrue(); assertThat(target.getSet().size()).isEqualTo(1); assertThat(target.getSet().containsAll(set)).isTrue(); @@ -1142,9 +1072,9 @@ public void setCollectionPropertyWithIntArrayValue() { assertThat(target.getList().containsAll(list)).isTrue(); } - @SuppressWarnings("unchecked") // list cannot be properly parameterized as it breaks other tests @Test - public void setCollectionPropertyWithIntegerValue() { + @SuppressWarnings("unchecked") // list cannot be properly parameterized as it breaks other tests + void setCollectionPropertyWithIntegerValue() { IndexedTestBean target = new IndexedTestBean(); AbstractPropertyAccessor accessor = createAccessor(target); Collection coll = new HashSet<>(); @@ -1159,7 +1089,7 @@ public void setCollectionPropertyWithIntegerValue() { Set list = new HashSet<>(); list.add(3); accessor.setPropertyValue("list", 3); - assertThat(target.getCollection().size()).isEqualTo(1); + assertThat(target.getCollection()).hasSize(1); assertThat(target.getCollection().containsAll(coll)).isTrue(); assertThat(target.getSet().size()).isEqualTo(1); assertThat(target.getSet().containsAll(set)).isTrue(); @@ -1169,9 +1099,9 @@ public void setCollectionPropertyWithIntegerValue() { assertThat(target.getList().containsAll(list)).isTrue(); } - @SuppressWarnings("unchecked") // list cannot be properly parameterized as it breaks other tests @Test - public void setCollectionPropertyWithStringValue() { + @SuppressWarnings("unchecked") // list cannot be properly parameterized as it breaks other tests + void setCollectionPropertyWithStringValue() { IndexedTestBean target = new IndexedTestBean(); AbstractPropertyAccessor accessor = createAccessor(target); List set = new ArrayList<>(); @@ -1192,7 +1122,7 @@ public void setCollectionPropertyWithStringValue() { } @Test - public void setCollectionPropertyWithStringValueAndCustomEditor() { + void setCollectionPropertyWithStringValueAndCustomEditor() { IndexedTestBean target = new IndexedTestBean(); AbstractPropertyAccessor accessor = createAccessor(target); accessor.registerCustomEditor(String.class, "set", new StringTrimmerEditor(false)); @@ -1213,7 +1143,7 @@ public void setCollectionPropertyWithStringValueAndCustomEditor() { } @Test - public void setMapProperty() { + void setMapProperty() { IndexedTestBean target = new IndexedTestBean(); AbstractPropertyAccessor accessor = createAccessor(target); Map map = new HashMap<>(); @@ -1227,7 +1157,8 @@ public void setMapProperty() { } @Test - public void setMapPropertyNonMatchingType() { + @SuppressWarnings("unchecked") + void setMapPropertyNonMatchingType() { IndexedTestBean target = new IndexedTestBean(); AbstractPropertyAccessor accessor = createAccessor(target); Map map = new TreeMap<>(); @@ -1236,14 +1167,14 @@ public void setMapPropertyNonMatchingType() { Map sortedMap = new TreeMap<>(); sortedMap.put("sortedKey", "sortedValue"); accessor.setPropertyValue("sortedMap", sortedMap); - assertThat(target.getMap().size()).isEqualTo(1); + assertThat(target.getMap()).hasSize(1); assertThat(target.getMap().get("key")).isEqualTo("value"); assertThat(target.getSortedMap().size()).isEqualTo(1); assertThat(target.getSortedMap().get("sortedKey")).isEqualTo("sortedValue"); } @Test - public void setMapPropertyWithTypeConversion() { + void setMapPropertyWithTypeConversion() { IndexedTestBean target = new IndexedTestBean(); AbstractPropertyAccessor accessor = createAccessor(target); accessor.registerCustomEditor(TestBean.class, new PropertyEditorSupport() { @@ -1272,7 +1203,7 @@ public void setAsText(String text) throws IllegalArgumentException { } @Test - public void setMapPropertyWithUnmodifiableMap() { + void setMapPropertyWithUnmodifiableMap() { IndexedTestBean target = new IndexedTestBean(); AbstractPropertyAccessor accessor = createAccessor(target); accessor.registerCustomEditor(TestBean.class, "map", new PropertyEditorSupport() { @@ -1296,7 +1227,7 @@ public void setAsText(String text) throws IllegalArgumentException { } @Test - public void setMapPropertyWithCustomUnmodifiableMap() { + void setMapPropertyWithCustomUnmodifiableMap() { IndexedTestBean target = new IndexedTestBean(); AbstractPropertyAccessor accessor = createAccessor(target); accessor.registerCustomEditor(TestBean.class, "map", new PropertyEditorSupport() { @@ -1319,9 +1250,9 @@ public void setAsText(String text) throws IllegalArgumentException { assertThat(((TestBean) target.getMap().get(2)).getName()).isEqualTo("rob"); } - @SuppressWarnings({ "unchecked", "rawtypes" }) // must work with raw map in this test @Test - public void setRawMapPropertyWithNoEditorRegistered() { + @SuppressWarnings({ "unchecked", "rawtypes" }) // must work with raw map in this test + void setRawMapPropertyWithNoEditorRegistered() { IndexedTestBean target = new IndexedTestBean(); AbstractPropertyAccessor accessor = createAccessor(target); Map inputMap = new HashMap(); @@ -1336,7 +1267,7 @@ public void setRawMapPropertyWithNoEditorRegistered() { } @Test - public void setUnknownProperty() { + void setUnknownProperty() { Simple target = new Simple("John", 2); AbstractPropertyAccessor accessor = createAccessor(target); assertThatExceptionOfType(NotWritablePropertyException.class).isThrownBy(() -> @@ -1349,7 +1280,7 @@ public void setUnknownProperty() { } @Test - public void setUnknownPropertyWithPossibleMatches() { + void setUnknownPropertyWithPossibleMatches() { Simple target = new Simple("John", 2); AbstractPropertyAccessor accessor = createAccessor(target); assertThatExceptionOfType(NotWritablePropertyException.class).isThrownBy(() -> @@ -1361,7 +1292,7 @@ public void setUnknownPropertyWithPossibleMatches() { } @Test - public void setUnknownOptionalProperty() { + void setUnknownOptionalProperty() { Simple target = new Simple("John", 2); AbstractPropertyAccessor accessor = createAccessor(target); PropertyValue value = new PropertyValue("foo", "value"); @@ -1370,7 +1301,7 @@ public void setUnknownOptionalProperty() { } @Test - public void setPropertyInProtectedBaseBean() { + void setPropertyInProtectedBaseBean() { DerivedFromProtectedBaseBean target = new DerivedFromProtectedBaseBean(); AbstractPropertyAccessor accessor = createAccessor(target); accessor.setPropertyValue("someProperty", "someValue"); @@ -1379,7 +1310,7 @@ public void setPropertyInProtectedBaseBean() { } @Test - public void setPropertyTypeMismatch() { + void setPropertyTypeMismatch() { TestBean target = new TestBean(); AbstractPropertyAccessor accessor = createAccessor(target); assertThatExceptionOfType(TypeMismatchException.class).isThrownBy(() -> @@ -1387,7 +1318,7 @@ public void setPropertyTypeMismatch() { } @Test - public void setEmptyValueForPrimitiveProperty() { + void setEmptyValueForPrimitiveProperty() { TestBean target = new TestBean(); AbstractPropertyAccessor accessor = createAccessor(target); assertThatExceptionOfType(TypeMismatchException.class).isThrownBy(() -> @@ -1395,7 +1326,7 @@ public void setEmptyValueForPrimitiveProperty() { } @Test - public void setUnknownNestedProperty() { + void setUnknownNestedProperty() { Person target = createPerson("John", "Paris", "FR"); AbstractPropertyAccessor accessor = createAccessor(target); @@ -1404,7 +1335,7 @@ public void setUnknownNestedProperty() { } @Test - public void setPropertyValuesIgnoresInvalidNestedOnRequest() { + void setPropertyValuesIgnoresInvalidNestedOnRequest() { ITestBean target = new TestBean(); MutablePropertyValues pvs = new MutablePropertyValues(); pvs.addPropertyValue(new PropertyValue("name", "rod")); @@ -1418,7 +1349,7 @@ public void setPropertyValuesIgnoresInvalidNestedOnRequest() { } @Test - public void getAndSetIndexedProperties() { + void getAndSetIndexedProperties() { IndexedTestBean target = new IndexedTestBean(); AbstractPropertyAccessor accessor = createAccessor(target); TestBean tb0 = target.getArray()[0]; @@ -1488,7 +1419,7 @@ public void getAndSetIndexedProperties() { } @Test - public void getAndSetIndexedPropertiesWithDirectAccess() { + void getAndSetIndexedPropertiesWithDirectAccess() { IndexedTestBean target = new IndexedTestBean(); AbstractPropertyAccessor accessor = createAccessor(target); TestBean tb0 = target.getArray()[0]; @@ -1527,7 +1458,7 @@ public void getAndSetIndexedPropertiesWithDirectAccess() { assertThat((target.getList().get(0))).isEqualTo(tb3); assertThat((target.getList().get(1))).isEqualTo(tb2); assertThat((target.getList().get(2))).isEqualTo(tb0); - assertThat((target.getList().get(3))).isEqualTo(null); + assertThat((target.getList().get(3))).isNull(); assertThat((target.getList().get(4))).isEqualTo(tb1); assertThat((target.getMap().get("key1"))).isEqualTo(tb1); assertThat((target.getMap().get("key2"))).isEqualTo(tb0); @@ -1538,7 +1469,7 @@ public void getAndSetIndexedPropertiesWithDirectAccess() { assertThat(accessor.getPropertyValue("list[0]")).isEqualTo(tb3); assertThat(accessor.getPropertyValue("list[1]")).isEqualTo(tb2); assertThat(accessor.getPropertyValue("list[2]")).isEqualTo(tb0); - assertThat(accessor.getPropertyValue("list[3]")).isEqualTo(null); + assertThat(accessor.getPropertyValue("list[3]")).isNull(); assertThat(accessor.getPropertyValue("list[4]")).isEqualTo(tb1); assertThat(accessor.getPropertyValue("map[\"key1\"]")).isEqualTo(tb1); assertThat(accessor.getPropertyValue("map['key2']")).isEqualTo(tb0); @@ -1547,7 +1478,7 @@ public void getAndSetIndexedPropertiesWithDirectAccess() { } @Test - public void propertyType() { + void propertyType() { Person target = createPerson("John", "Paris", "FR"); AbstractPropertyAccessor accessor = createAccessor(target); @@ -1555,7 +1486,7 @@ public void propertyType() { } @Test - public void propertyTypeUnknownProperty() { + void propertyTypeUnknownProperty() { Simple target = new Simple("John", 2); AbstractPropertyAccessor accessor = createAccessor(target); @@ -1563,7 +1494,7 @@ public void propertyTypeUnknownProperty() { } @Test - public void propertyTypeDescriptor() { + void propertyTypeDescriptor() { Person target = createPerson("John", "Paris", "FR"); AbstractPropertyAccessor accessor = createAccessor(target); @@ -1571,7 +1502,7 @@ public void propertyTypeDescriptor() { } @Test - public void propertyTypeDescriptorUnknownProperty() { + void propertyTypeDescriptorUnknownProperty() { Simple target = new Simple("John", 2); AbstractPropertyAccessor accessor = createAccessor(target); @@ -1579,10 +1510,10 @@ public void propertyTypeDescriptorUnknownProperty() { } @Test - public void propertyTypeIndexedProperty() { + void propertyTypeIndexedProperty() { IndexedTestBean target = new IndexedTestBean(); AbstractPropertyAccessor accessor = createAccessor(target); - assertThat(accessor.getPropertyType("map[key0]")).isEqualTo(null); + assertThat(accessor.getPropertyType("map[key0]")).isNull(); accessor = createAccessor(target); accessor.setPropertyValue("map[key0]", "my String"); @@ -1594,7 +1525,7 @@ public void propertyTypeIndexedProperty() { } @Test - public void cornerSpr10115() { + void cornerSpr10115() { Spr10115Bean target = new Spr10115Bean(); AbstractPropertyAccessor accessor = createAccessor(target); accessor.setPropertyValue("prop1", "val1"); @@ -1602,7 +1533,7 @@ public void cornerSpr10115() { } @Test - public void cornerSpr13837() { + void cornerSpr13837() { Spr13837Bean target = new Spr13837Bean(); AbstractPropertyAccessor accessor = createAccessor(target); accessor.setPropertyValue("something", 42); diff --git a/spring-beans/src/test/java/org/springframework/beans/BeanUtilsTests.java b/spring-beans/src/test/java/org/springframework/beans/BeanUtilsTests.java index f3e9d2eaa9a1..b90fd515dc36 100644 --- a/spring-beans/src/test/java/org/springframework/beans/BeanUtilsTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/BeanUtilsTests.java @@ -49,6 +49,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.assertj.core.api.SoftAssertions.assertSoftly; /** * Unit tests for {@link BeanUtils}. @@ -85,19 +86,43 @@ void instantiateClassWithOptionalNullableType() throws NoSuchMethodException { } @Test // gh-22531 - void instantiateClassWithOptionalPrimitiveType() throws NoSuchMethodException { - Constructor ctor = BeanWithPrimitiveTypes.class.getDeclaredConstructor(int.class, boolean.class, String.class); - BeanWithPrimitiveTypes bean = BeanUtils.instantiateClass(ctor, null, null, "foo"); - assertThat(bean.getCounter()).isEqualTo(0); - assertThat(bean.isFlag()).isEqualTo(false); - assertThat(bean.getValue()).isEqualTo("foo"); + void instantiateClassWithFewerArgsThanParameters() throws NoSuchMethodException { + Constructor constructor = getBeanWithPrimitiveTypesConstructor(); + + assertThatExceptionOfType(BeanInstantiationException.class).isThrownBy(() -> + BeanUtils.instantiateClass(constructor, null, null, "foo")); } @Test // gh-22531 void instantiateClassWithMoreArgsThanParameters() throws NoSuchMethodException { - Constructor ctor = BeanWithPrimitiveTypes.class.getDeclaredConstructor(int.class, boolean.class, String.class); + Constructor constructor = getBeanWithPrimitiveTypesConstructor(); + assertThatExceptionOfType(BeanInstantiationException.class).isThrownBy(() -> - BeanUtils.instantiateClass(ctor, null, null, "foo", null)); + BeanUtils.instantiateClass(constructor, null, null, null, null, null, null, null, null, "foo", null)); + } + + @Test // gh-22531, gh-27390 + void instantiateClassWithOptionalPrimitiveTypes() throws NoSuchMethodException { + Constructor constructor = getBeanWithPrimitiveTypesConstructor(); + + BeanWithPrimitiveTypes bean = BeanUtils.instantiateClass(constructor, null, null, null, null, null, null, null, null, "foo"); + + assertSoftly(softly -> { + softly.assertThat(bean.isFlag()).isFalse(); + softly.assertThat(bean.getByteCount()).isEqualTo((byte) 0); + softly.assertThat(bean.getShortCount()).isEqualTo((short) 0); + softly.assertThat(bean.getIntCount()).isEqualTo(0); + softly.assertThat(bean.getLongCount()).isEqualTo(0L); + softly.assertThat(bean.getFloatCount()).isEqualTo(0F); + softly.assertThat(bean.getDoubleCount()).isEqualTo(0D); + softly.assertThat(bean.getCharacter()).isEqualTo('\0'); + softly.assertThat(bean.getText()).isEqualTo("foo"); + }); + } + + private Constructor getBeanWithPrimitiveTypesConstructor() throws NoSuchMethodException { + return BeanWithPrimitiveTypes.class.getConstructor(boolean.class, byte.class, short.class, int.class, + long.class, float.class, double.class, char.class, String.class); } @Test @@ -628,30 +653,68 @@ public String getValue() { private static class BeanWithPrimitiveTypes { - private int counter; - private boolean flag; + private byte byteCount; + private short shortCount; + private int intCount; + private long longCount; + private float floatCount; + private double doubleCount; + private char character; + private String text; - private String value; @SuppressWarnings("unused") - public BeanWithPrimitiveTypes(int counter, boolean flag, String value) { - this.counter = counter; - this.flag = flag; - this.value = value; - } + public BeanWithPrimitiveTypes(boolean flag, byte byteCount, short shortCount, int intCount, long longCount, + float floatCount, double doubleCount, char character, String text) { - public int getCounter() { - return counter; + this.flag = flag; + this.byteCount = byteCount; + this.shortCount = shortCount; + this.intCount = intCount; + this.longCount = longCount; + this.floatCount = floatCount; + this.doubleCount = doubleCount; + this.character = character; + this.text = text; } public boolean isFlag() { return flag; } - public String getValue() { - return value; + public byte getByteCount() { + return byteCount; } + + public short getShortCount() { + return shortCount; + } + + public int getIntCount() { + return intCount; + } + + public long getLongCount() { + return longCount; + } + + public float getFloatCount() { + return floatCount; + } + + public double getDoubleCount() { + return doubleCount; + } + + public char getCharacter() { + return character; + } + + public String getText() { + return text; + } + } private static class PrivateBeanWithPrivateConstructor { diff --git a/spring-beans/src/test/java/org/springframework/beans/BeanWrapperAutoGrowingTests.java b/spring-beans/src/test/java/org/springframework/beans/BeanWrapperAutoGrowingTests.java index 2dddf884e319..78524e632b0c 100644 --- a/spring-beans/src/test/java/org/springframework/beans/BeanWrapperAutoGrowingTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/BeanWrapperAutoGrowingTests.java @@ -38,7 +38,7 @@ public class BeanWrapperAutoGrowingTests { @BeforeEach - public void setUp() { + public void setup() { wrapper.setAutoGrowNestedPaths(true); } diff --git a/spring-beans/src/test/java/org/springframework/beans/BeanWrapperGenericsTests.java b/spring-beans/src/test/java/org/springframework/beans/BeanWrapperGenericsTests.java index be0c2cc5953a..760e98cf9351 100644 --- a/spring-beans/src/test/java/org/springframework/beans/BeanWrapperGenericsTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/BeanWrapperGenericsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -16,7 +16,6 @@ package org.springframework.beans; -import java.net.MalformedURLException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -46,10 +45,10 @@ * @author Chris Beams * @since 18.01.2006 */ -public class BeanWrapperGenericsTests { +class BeanWrapperGenericsTests { @Test - public void testGenericSet() { + void testGenericSet() { GenericBean gb = new GenericBean<>(); BeanWrapper bw = new BeanWrapperImpl(gb); Set input = new HashSet<>(); @@ -61,7 +60,7 @@ public void testGenericSet() { } @Test - public void testGenericLowerBoundedSet() { + void testGenericLowerBoundedSet() { GenericBean gb = new GenericBean<>(); BeanWrapper bw = new BeanWrapperImpl(gb); bw.registerCustomEditor(Number.class, new CustomNumberEditor(Integer.class, true)); @@ -74,7 +73,7 @@ public void testGenericLowerBoundedSet() { } @Test - public void testGenericSetWithConversionFailure() { + void testGenericSetWithConversionFailure() { GenericBean gb = new GenericBean<>(); BeanWrapper bw = new BeanWrapperImpl(gb); Set input = new HashSet<>(); @@ -85,7 +84,7 @@ public void testGenericSetWithConversionFailure() { } @Test - public void testGenericList() throws MalformedURLException { + void testGenericList() throws Exception { GenericBean gb = new GenericBean<>(); BeanWrapper bw = new BeanWrapperImpl(gb); List input = new ArrayList<>(); @@ -97,7 +96,7 @@ public void testGenericList() throws MalformedURLException { } @Test - public void testGenericListElement() throws MalformedURLException { + void testGenericListElement() throws Exception { GenericBean gb = new GenericBean<>(); gb.setResourceList(new ArrayList<>()); BeanWrapper bw = new BeanWrapperImpl(gb); @@ -106,29 +105,29 @@ public void testGenericListElement() throws MalformedURLException { } @Test - public void testGenericMap() { + void testGenericMap() { GenericBean gb = new GenericBean<>(); BeanWrapper bw = new BeanWrapperImpl(gb); Map input = new HashMap<>(); input.put("4", "5"); input.put("6", "7"); bw.setPropertyValue("shortMap", input); - assertThat(gb.getShortMap().get(new Short("4"))).isEqualTo(5); - assertThat(gb.getShortMap().get(new Short("6"))).isEqualTo(7); + assertThat(gb.getShortMap().get(Short.valueOf("4"))).isEqualTo(5); + assertThat(gb.getShortMap().get(Short.valueOf("6"))).isEqualTo(7); } @Test - public void testGenericMapElement() { + void testGenericMapElement() { GenericBean gb = new GenericBean<>(); gb.setShortMap(new HashMap<>()); BeanWrapper bw = new BeanWrapperImpl(gb); bw.setPropertyValue("shortMap[4]", "5"); assertThat(bw.getPropertyValue("shortMap[4]")).isEqualTo(5); - assertThat(gb.getShortMap().get(new Short("4"))).isEqualTo(5); + assertThat(gb.getShortMap().get(Short.valueOf("4"))).isEqualTo(5); } @Test - public void testGenericMapWithKeyType() { + void testGenericMapWithKeyType() { GenericBean gb = new GenericBean<>(); BeanWrapper bw = new BeanWrapperImpl(gb); Map input = new HashMap<>(); @@ -140,17 +139,17 @@ public void testGenericMapWithKeyType() { } @Test - public void testGenericMapElementWithKeyType() { + void testGenericMapElementWithKeyType() { GenericBean gb = new GenericBean<>(); gb.setLongMap(new HashMap()); BeanWrapper bw = new BeanWrapperImpl(gb); bw.setPropertyValue("longMap[4]", "5"); - assertThat(gb.getLongMap().get(new Long("4"))).isEqualTo("5"); + assertThat(gb.getLongMap().get(Long.valueOf("4"))).isEqualTo("5"); assertThat(bw.getPropertyValue("longMap[4]")).isEqualTo("5"); } @Test - public void testGenericMapWithCollectionValue() { + void testGenericMapWithCollectionValue() { GenericBean gb = new GenericBean<>(); BeanWrapper bw = new BeanWrapperImpl(gb); bw.registerCustomEditor(Number.class, new CustomNumberEditor(Integer.class, false)); @@ -162,14 +161,12 @@ public void testGenericMapWithCollectionValue() { value2.add(Boolean.TRUE); input.put("2", value2); bw.setPropertyValue("collectionMap", input); - boolean condition1 = gb.getCollectionMap().get(1) instanceof HashSet; - assertThat(condition1).isTrue(); - boolean condition = gb.getCollectionMap().get(2) instanceof ArrayList; - assertThat(condition).isTrue(); + assertThat(gb.getCollectionMap().get(1) instanceof HashSet).isTrue(); + assertThat(gb.getCollectionMap().get(2) instanceof ArrayList).isTrue(); } @Test - public void testGenericMapElementWithCollectionValue() { + void testGenericMapElementWithCollectionValue() { GenericBean gb = new GenericBean<>(); gb.setCollectionMap(new HashMap<>()); BeanWrapper bw = new BeanWrapperImpl(gb); @@ -177,24 +174,23 @@ public void testGenericMapElementWithCollectionValue() { HashSet value1 = new HashSet<>(); value1.add(1); bw.setPropertyValue("collectionMap[1]", value1); - boolean condition = gb.getCollectionMap().get(1) instanceof HashSet; - assertThat(condition).isTrue(); + assertThat(gb.getCollectionMap().get(1) instanceof HashSet).isTrue(); } @Test - public void testGenericMapFromProperties() { + void testGenericMapFromProperties() { GenericBean gb = new GenericBean<>(); BeanWrapper bw = new BeanWrapperImpl(gb); Properties input = new Properties(); input.setProperty("4", "5"); input.setProperty("6", "7"); bw.setPropertyValue("shortMap", input); - assertThat(gb.getShortMap().get(new Short("4"))).isEqualTo(5); - assertThat(gb.getShortMap().get(new Short("6"))).isEqualTo(7); + assertThat(gb.getShortMap().get(Short.valueOf("4"))).isEqualTo(5); + assertThat(gb.getShortMap().get(Short.valueOf("6"))).isEqualTo(7); } @Test - public void testGenericListOfLists() throws MalformedURLException { + void testGenericListOfLists() { GenericBean gb = new GenericBean<>(); List> list = new ArrayList<>(); list.add(new ArrayList<>()); @@ -206,7 +202,7 @@ public void testGenericListOfLists() throws MalformedURLException { } @Test - public void testGenericListOfListsWithElementConversion() throws MalformedURLException { + void testGenericListOfListsWithElementConversion() { GenericBean gb = new GenericBean<>(); List> list = new ArrayList<>(); list.add(new ArrayList<>()); @@ -218,7 +214,7 @@ public void testGenericListOfListsWithElementConversion() throws MalformedURLExc } @Test - public void testGenericListOfArrays() throws MalformedURLException { + void testGenericListOfArrays() { GenericBean gb = new GenericBean<>(); ArrayList list = new ArrayList<>(); list.add(new String[] {"str1", "str2"}); @@ -230,7 +226,7 @@ public void testGenericListOfArrays() throws MalformedURLException { } @Test - public void testGenericListOfArraysWithElementConversion() throws MalformedURLException { + void testGenericListOfArraysWithElementConversion() { GenericBean gb = new GenericBean<>(); ArrayList list = new ArrayList<>(); list.add(new String[] {"str1", "str2"}); @@ -243,55 +239,55 @@ public void testGenericListOfArraysWithElementConversion() throws MalformedURLEx } @Test - public void testGenericListOfMaps() throws MalformedURLException { + void testGenericListOfMaps() { GenericBean gb = new GenericBean<>(); List> list = new ArrayList<>(); list.add(new HashMap<>()); gb.setListOfMaps(list); BeanWrapper bw = new BeanWrapperImpl(gb); - bw.setPropertyValue("listOfMaps[0][10]", new Long(5)); - assertThat(bw.getPropertyValue("listOfMaps[0][10]")).isEqualTo(new Long(5)); - assertThat(gb.getListOfMaps().get(0).get(10)).isEqualTo(new Long(5)); + bw.setPropertyValue("listOfMaps[0][10]", 5L); + assertThat(bw.getPropertyValue("listOfMaps[0][10]")).isEqualTo(5L); + assertThat(gb.getListOfMaps().get(0).get(10)).isEqualTo(Long.valueOf(5)); } @Test - public void testGenericListOfMapsWithElementConversion() throws MalformedURLException { + void testGenericListOfMapsWithElementConversion() { GenericBean gb = new GenericBean<>(); List> list = new ArrayList<>(); list.add(new HashMap<>()); gb.setListOfMaps(list); BeanWrapper bw = new BeanWrapperImpl(gb); bw.setPropertyValue("listOfMaps[0][10]", "5"); - assertThat(bw.getPropertyValue("listOfMaps[0][10]")).isEqualTo(new Long(5)); - assertThat(gb.getListOfMaps().get(0).get(10)).isEqualTo(new Long(5)); + assertThat(bw.getPropertyValue("listOfMaps[0][10]")).isEqualTo(5L); + assertThat(gb.getListOfMaps().get(0).get(10)).isEqualTo(Long.valueOf(5)); } @Test - public void testGenericMapOfMaps() throws MalformedURLException { + void testGenericMapOfMaps() { GenericBean gb = new GenericBean<>(); Map> map = new HashMap<>(); map.put("mykey", new HashMap<>()); gb.setMapOfMaps(map); BeanWrapper bw = new BeanWrapperImpl(gb); - bw.setPropertyValue("mapOfMaps[mykey][10]", new Long(5)); - assertThat(bw.getPropertyValue("mapOfMaps[mykey][10]")).isEqualTo(new Long(5)); - assertThat(gb.getMapOfMaps().get("mykey").get(10)).isEqualTo(new Long(5)); + bw.setPropertyValue("mapOfMaps[mykey][10]", 5L); + assertThat(bw.getPropertyValue("mapOfMaps[mykey][10]")).isEqualTo(5L); + assertThat(gb.getMapOfMaps().get("mykey").get(10)).isEqualTo(Long.valueOf(5)); } @Test - public void testGenericMapOfMapsWithElementConversion() throws MalformedURLException { + void testGenericMapOfMapsWithElementConversion() { GenericBean gb = new GenericBean<>(); Map> map = new HashMap<>(); map.put("mykey", new HashMap<>()); gb.setMapOfMaps(map); BeanWrapper bw = new BeanWrapperImpl(gb); bw.setPropertyValue("mapOfMaps[mykey][10]", "5"); - assertThat(bw.getPropertyValue("mapOfMaps[mykey][10]")).isEqualTo(new Long(5)); - assertThat(gb.getMapOfMaps().get("mykey").get(10)).isEqualTo(new Long(5)); + assertThat(bw.getPropertyValue("mapOfMaps[mykey][10]")).isEqualTo(Long.valueOf(5)); + assertThat(gb.getMapOfMaps().get("mykey").get(10)).isEqualTo(Long.valueOf(5)); } @Test - public void testGenericMapOfLists() throws MalformedURLException { + void testGenericMapOfLists() { GenericBean gb = new GenericBean<>(); Map> map = new HashMap<>(); map.put(1, new ArrayList<>()); @@ -303,7 +299,7 @@ public void testGenericMapOfLists() throws MalformedURLException { } @Test - public void testGenericMapOfListsWithElementConversion() throws MalformedURLException { + void testGenericMapOfListsWithElementConversion() { GenericBean gb = new GenericBean<>(); Map> map = new HashMap<>(); map.put(1, new ArrayList<>()); @@ -315,7 +311,7 @@ public void testGenericMapOfListsWithElementConversion() throws MalformedURLExce } @Test - public void testGenericTypeNestingMapOfInteger() throws Exception { + void testGenericTypeNestingMapOfInteger() { Map map = new HashMap<>(); map.put("testKey", "100"); @@ -324,14 +320,13 @@ public void testGenericTypeNestingMapOfInteger() throws Exception { bw.setPropertyValue("mapOfInteger", map); Object obj = gb.getMapOfInteger().get("testKey"); - boolean condition = obj instanceof Integer; - assertThat(condition).isTrue(); + assertThat(obj instanceof Integer).isTrue(); } @Test - public void testGenericTypeNestingMapOfListOfInteger() throws Exception { + void testGenericTypeNestingMapOfListOfInteger() { Map> map = new HashMap<>(); - List list = Arrays.asList(new String[] {"1", "2", "3"}); + List list = Arrays.asList("1", "2", "3"); map.put("testKey", list); NestedGenericCollectionBean gb = new NestedGenericCollectionBean(); @@ -339,13 +334,12 @@ public void testGenericTypeNestingMapOfListOfInteger() throws Exception { bw.setPropertyValue("mapOfListOfInteger", map); Object obj = gb.getMapOfListOfInteger().get("testKey").get(0); - boolean condition = obj instanceof Integer; - assertThat(condition).isTrue(); + assertThat(obj instanceof Integer).isTrue(); assertThat(((Integer) obj).intValue()).isEqualTo(1); } @Test - public void testGenericTypeNestingListOfMapOfInteger() throws Exception { + void testGenericTypeNestingListOfMapOfInteger() { List> list = new ArrayList<>(); Map map = new HashMap<>(); map.put("testKey", "5"); @@ -356,15 +350,14 @@ public void testGenericTypeNestingListOfMapOfInteger() throws Exception { bw.setPropertyValue("listOfMapOfInteger", list); Object obj = gb.getListOfMapOfInteger().get(0).get("testKey"); - boolean condition = obj instanceof Integer; - assertThat(condition).isTrue(); + assertThat(obj instanceof Integer).isTrue(); assertThat(((Integer) obj).intValue()).isEqualTo(5); } @Test - public void testGenericTypeNestingMapOfListOfListOfInteger() throws Exception { + void testGenericTypeNestingMapOfListOfListOfInteger() { Map>> map = new HashMap<>(); - List list = Arrays.asList(new String[] {"1", "2", "3"}); + List list = Arrays.asList("1", "2", "3"); map.put("testKey", Collections.singletonList(list)); NestedGenericCollectionBean gb = new NestedGenericCollectionBean(); @@ -372,13 +365,12 @@ public void testGenericTypeNestingMapOfListOfListOfInteger() throws Exception { bw.setPropertyValue("mapOfListOfListOfInteger", map); Object obj = gb.getMapOfListOfListOfInteger().get("testKey").get(0).get(0); - boolean condition = obj instanceof Integer; - assertThat(condition).isTrue(); + assertThat(obj instanceof Integer).isTrue(); assertThat(((Integer) obj).intValue()).isEqualTo(1); } @Test - public void testComplexGenericMap() { + void testComplexGenericMap() { Map, List> inputMap = new HashMap<>(); List inputKey = new ArrayList<>(); inputKey.add("1"); @@ -391,11 +383,11 @@ public void testComplexGenericMap() { bw.setPropertyValue("genericMap", inputMap); assertThat(holder.getGenericMap().keySet().iterator().next().get(0)).isEqualTo(1); - assertThat(holder.getGenericMap().values().iterator().next().get(0)).isEqualTo(new Long(10)); + assertThat(holder.getGenericMap().values().iterator().next().get(0)).isEqualTo(Long.valueOf(10)); } @Test - public void testComplexGenericMapWithCollectionConversion() { + void testComplexGenericMapWithCollectionConversion() { Map, Set> inputMap = new HashMap<>(); Set inputKey = new HashSet<>(); inputKey.add("1"); @@ -408,11 +400,11 @@ public void testComplexGenericMapWithCollectionConversion() { bw.setPropertyValue("genericMap", inputMap); assertThat(holder.getGenericMap().keySet().iterator().next().get(0)).isEqualTo(1); - assertThat(holder.getGenericMap().values().iterator().next().get(0)).isEqualTo(new Long(10)); + assertThat(holder.getGenericMap().values().iterator().next().get(0)).isEqualTo(Long.valueOf(10)); } @Test - public void testComplexGenericIndexedMapEntry() { + void testComplexGenericIndexedMapEntry() { List inputValue = new ArrayList<>(); inputValue.add("10"); @@ -421,11 +413,11 @@ public void testComplexGenericIndexedMapEntry() { bw.setPropertyValue("genericIndexedMap[1]", inputValue); assertThat(holder.getGenericIndexedMap().keySet().iterator().next()).isEqualTo(1); - assertThat(holder.getGenericIndexedMap().values().iterator().next().get(0)).isEqualTo(new Long(10)); + assertThat(holder.getGenericIndexedMap().values().iterator().next().get(0)).isEqualTo(Long.valueOf(10)); } @Test - public void testComplexGenericIndexedMapEntryWithCollectionConversion() { + void testComplexGenericIndexedMapEntryWithCollectionConversion() { Set inputValue = new HashSet<>(); inputValue.add("10"); @@ -434,11 +426,11 @@ public void testComplexGenericIndexedMapEntryWithCollectionConversion() { bw.setPropertyValue("genericIndexedMap[1]", inputValue); assertThat(holder.getGenericIndexedMap().keySet().iterator().next()).isEqualTo(1); - assertThat(holder.getGenericIndexedMap().values().iterator().next().get(0)).isEqualTo(new Long(10)); + assertThat(holder.getGenericIndexedMap().values().iterator().next().get(0)).isEqualTo(Long.valueOf(10)); } @Test - public void testComplexDerivedIndexedMapEntry() { + void testComplexDerivedIndexedMapEntry() { List inputValue = new ArrayList<>(); inputValue.add("10"); @@ -447,11 +439,11 @@ public void testComplexDerivedIndexedMapEntry() { bw.setPropertyValue("derivedIndexedMap[1]", inputValue); assertThat(holder.getDerivedIndexedMap().keySet().iterator().next()).isEqualTo(1); - assertThat(holder.getDerivedIndexedMap().values().iterator().next().get(0)).isEqualTo(new Long(10)); + assertThat(holder.getDerivedIndexedMap().values().iterator().next().get(0)).isEqualTo(Long.valueOf(10)); } @Test - public void testComplexDerivedIndexedMapEntryWithCollectionConversion() { + void testComplexDerivedIndexedMapEntryWithCollectionConversion() { Set inputValue = new HashSet<>(); inputValue.add("10"); @@ -460,11 +452,11 @@ public void testComplexDerivedIndexedMapEntryWithCollectionConversion() { bw.setPropertyValue("derivedIndexedMap[1]", inputValue); assertThat(holder.getDerivedIndexedMap().keySet().iterator().next()).isEqualTo(1); - assertThat(holder.getDerivedIndexedMap().values().iterator().next().get(0)).isEqualTo(new Long(10)); + assertThat(holder.getDerivedIndexedMap().values().iterator().next().get(0)).isEqualTo(Long.valueOf(10)); } @Test - public void testGenericallyTypedIntegerBean() throws Exception { + void testGenericallyTypedIntegerBean() { GenericIntegerBean gb = new GenericIntegerBean(); BeanWrapper bw = new BeanWrapperImpl(gb); bw.setPropertyValue("genericProperty", "10"); @@ -475,7 +467,7 @@ public void testGenericallyTypedIntegerBean() throws Exception { } @Test - public void testGenericallyTypedSetOfIntegerBean() throws Exception { + void testGenericallyTypedSetOfIntegerBean() { GenericSetOfIntegerBean gb = new GenericSetOfIntegerBean(); BeanWrapper bw = new BeanWrapperImpl(gb); bw.setPropertyValue("genericProperty", "10"); @@ -486,23 +478,23 @@ public void testGenericallyTypedSetOfIntegerBean() throws Exception { } @Test - public void testSettingGenericPropertyWithReadOnlyInterface() { + void testSettingGenericPropertyWithReadOnlyInterface() { Bar bar = new Bar(); BeanWrapper bw = new BeanWrapperImpl(bar); bw.setPropertyValue("version", "10"); - assertThat(bar.getVersion()).isEqualTo(new Double(10.0)); + assertThat(bar.getVersion()).isEqualTo(Double.valueOf(10.0)); } @Test - public void testSettingLongPropertyWithGenericInterface() { + void testSettingLongPropertyWithGenericInterface() { Promotion bean = new Promotion(); BeanWrapper bw = new BeanWrapperImpl(bean); bw.setPropertyValue("id", "10"); - assertThat(bean.getId()).isEqualTo(new Long(10)); + assertThat(bean.getId()).isEqualTo(Long.valueOf(10)); } @Test - public void testUntypedPropertyWithMapAtRuntime() { + void testUntypedPropertyWithMapAtRuntime() { class Holder { private final D data; public Holder(D data) { diff --git a/spring-beans/src/test/java/org/springframework/beans/BeanWrapperTests.java b/spring-beans/src/test/java/org/springframework/beans/BeanWrapperTests.java index 0711189b5f59..8856e31a0e05 100644 --- a/spring-beans/src/test/java/org/springframework/beans/BeanWrapperTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/BeanWrapperTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -26,6 +26,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatNoException; /** * Specific {@link BeanWrapperImpl} tests. @@ -37,7 +38,7 @@ * @author Chris Beams * @author Dave Syer */ -public class BeanWrapperTests extends AbstractPropertyAccessorTests { +class BeanWrapperTests extends AbstractPropertyAccessorTests { @Override protected BeanWrapperImpl createAccessor(Object target) { @@ -46,7 +47,7 @@ protected BeanWrapperImpl createAccessor(Object target) { @Test - public void setterDoesNotCallGetter() { + void setterDoesNotCallGetter() { GetterBean target = new GetterBean(); BeanWrapper accessor = createAccessor(target); accessor.setPropertyValue("name", "tom"); @@ -55,7 +56,7 @@ public void setterDoesNotCallGetter() { } @Test - public void getterSilentlyFailWithOldValueExtraction() { + void getterSilentlyFailWithOldValueExtraction() { GetterBean target = new GetterBean(); BeanWrapper accessor = createAccessor(target); accessor.setExtractOldValueForEditor(true); // This will call the getter @@ -65,7 +66,7 @@ public void getterSilentlyFailWithOldValueExtraction() { } @Test - public void aliasedSetterThroughDefaultMethod() { + void aliasedSetterThroughDefaultMethod() { GetterBean target = new GetterBean(); BeanWrapper accessor = createAccessor(target); accessor.setPropertyValue("aliasedName", "tom"); @@ -74,7 +75,7 @@ public void aliasedSetterThroughDefaultMethod() { } @Test - public void setValidAndInvalidPropertyValuesShouldContainExceptionDetails() { + void setValidAndInvalidPropertyValuesShouldContainExceptionDetails() { TestBean target = new TestBean(); String newName = "tony"; String invalidTouchy = ".valid"; @@ -91,12 +92,12 @@ public void setValidAndInvalidPropertyValuesShouldContainExceptionDetails() { .getNewValue()).isEqualTo(invalidTouchy); }); // Test validly set property matches - assertThat(target.getName().equals(newName)).as("Valid set property must stick").isTrue(); - assertThat(target.getAge() == 0).as("Invalid set property must retain old value").isTrue(); + assertThat(target.getName()).as("Valid set property must stick").isEqualTo(newName); + assertThat(target.getAge()).as("Invalid set property must retain old value").isEqualTo(0); } @Test - public void checkNotWritablePropertyHoldPossibleMatches() { + void checkNotWritablePropertyHoldPossibleMatches() { TestBean target = new TestBean(); BeanWrapper accessor = createAccessor(target); assertThatExceptionOfType(NotWritablePropertyException.class).isThrownBy(() -> @@ -105,15 +106,15 @@ public void checkNotWritablePropertyHoldPossibleMatches() { } @Test // Can't be shared; there is no such thing as a read-only field - public void setReadOnlyMapProperty() { + void setReadOnlyMapProperty() { TypedReadOnlyMap map = new TypedReadOnlyMap(Collections.singletonMap("key", new TestBean())); TypedReadOnlyMapClient target = new TypedReadOnlyMapClient(); BeanWrapper accessor = createAccessor(target); - accessor.setPropertyValue("map", map); + assertThatNoException().isThrownBy(() -> accessor.setPropertyValue("map", map)); } @Test - public void notWritablePropertyExceptionContainsAlternativeMatch() { + void notWritablePropertyExceptionContainsAlternativeMatch() { IntelliBean target = new IntelliBean(); BeanWrapper bw = createAccessor(target); try { @@ -121,12 +122,12 @@ public void notWritablePropertyExceptionContainsAlternativeMatch() { } catch (NotWritablePropertyException ex) { assertThat(ex.getPossibleMatches()).as("Possible matches not determined").isNotNull(); - assertThat(ex.getPossibleMatches().length).as("Invalid amount of alternatives").isEqualTo(1); + assertThat(ex.getPossibleMatches()).as("Invalid amount of alternatives").hasSize(1); } } @Test - public void notWritablePropertyExceptionContainsAlternativeMatches() { + void notWritablePropertyExceptionContainsAlternativeMatches() { IntelliBean target = new IntelliBean(); BeanWrapper bw = createAccessor(target); try { @@ -134,23 +135,23 @@ public void notWritablePropertyExceptionContainsAlternativeMatches() { } catch (NotWritablePropertyException ex) { assertThat(ex.getPossibleMatches()).as("Possible matches not determined").isNotNull(); - assertThat(ex.getPossibleMatches().length).as("Invalid amount of alternatives").isEqualTo(3); + assertThat(ex.getPossibleMatches()).as("Invalid amount of alternatives").hasSize(3); } } @Override @Test // Can't be shared: no type mismatch with a field - public void setPropertyTypeMismatch() { + void setPropertyTypeMismatch() { PropertyTypeMismatch target = new PropertyTypeMismatch(); BeanWrapper accessor = createAccessor(target); accessor.setPropertyValue("object", "a String"); assertThat(target.value).isEqualTo("a String"); - assertThat(target.getObject() == 8).isTrue(); + assertThat(target.getObject()).isEqualTo(8); assertThat(accessor.getPropertyValue("object")).isEqualTo(8); } @Test - public void propertyDescriptors() { + void propertyDescriptors() { TestBean target = new TestBean(); target.setSpouse(new TestBean()); BeanWrapper accessor = createAccessor(target); @@ -166,7 +167,7 @@ public void propertyDescriptors() { @Test @SuppressWarnings("unchecked") - public void getPropertyWithOptional() { + void getPropertyWithOptional() { GetterWithOptional target = new GetterWithOptional(); TestBean tb = new TestBean("x"); BeanWrapper accessor = createAccessor(target); @@ -189,7 +190,7 @@ public void getPropertyWithOptional() { } @Test - public void getPropertyWithOptionalAndAutoGrow() { + void getPropertyWithOptionalAndAutoGrow() { GetterWithOptional target = new GetterWithOptional(); BeanWrapper accessor = createAccessor(target); accessor.setAutoGrowNestedPaths(true); @@ -201,7 +202,7 @@ public void getPropertyWithOptionalAndAutoGrow() { } @Test - public void incompletelyQuotedKeyLeadsToPropertyException() { + void incompletelyQuotedKeyLeadsToPropertyException() { TestBean target = new TestBean(); BeanWrapper accessor = createAccessor(target); assertThatExceptionOfType(NotWritablePropertyException.class).isThrownBy(() -> diff --git a/spring-beans/src/test/java/org/springframework/beans/DirectFieldAccessorTests.java b/spring-beans/src/test/java/org/springframework/beans/DirectFieldAccessorTests.java index 1ca8ddc60298..2cbe8f2ff41c 100644 --- a/spring-beans/src/test/java/org/springframework/beans/DirectFieldAccessorTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/DirectFieldAccessorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -29,7 +29,7 @@ * @author Chris Beams * @author Stephane Nicoll */ -public class DirectFieldAccessorTests extends AbstractPropertyAccessorTests { +class DirectFieldAccessorTests extends AbstractPropertyAccessorTests { @Override protected DirectFieldAccessor createAccessor(Object target) { @@ -38,7 +38,7 @@ protected DirectFieldAccessor createAccessor(Object target) { @Test - public void withShadowedField() { + void withShadowedField() { final StringBuilder sb = new StringBuilder(); TestBean target = new TestBean() { diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java index 13321a7e9a2e..8d6f823a7583 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -182,9 +182,9 @@ void prototypeFactoryBeanIgnoredByNonEagerTypeMatching() { assertThat(!DummyFactory.wasPrototypeCreated()).as("prototype not instantiated").isTrue(); String[] beanNames = lbf.getBeanNamesForType(TestBean.class, true, false); - assertThat(beanNames.length).isEqualTo(0); + assertThat(beanNames).hasSize(0); beanNames = lbf.getBeanNamesForAnnotation(SuppressWarnings.class); - assertThat(beanNames.length).isEqualTo(0); + assertThat(beanNames).hasSize(0); assertThat(lbf.containsSingleton("x1")).isFalse(); assertThat(lbf.containsBean("x1")).isTrue(); @@ -216,9 +216,9 @@ void singletonFactoryBeanIgnoredByNonEagerTypeMatching() { assertThat(!DummyFactory.wasPrototypeCreated()).as("prototype not instantiated").isTrue(); String[] beanNames = lbf.getBeanNamesForType(TestBean.class, true, false); - assertThat(beanNames.length).isEqualTo(0); + assertThat(beanNames).hasSize(0); beanNames = lbf.getBeanNamesForAnnotation(SuppressWarnings.class); - assertThat(beanNames.length).isEqualTo(0); + assertThat(beanNames).hasSize(0); assertThat(lbf.containsSingleton("x1")).isFalse(); assertThat(lbf.containsBean("x1")).isTrue(); @@ -249,9 +249,9 @@ void nonInitializedFactoryBeanIgnoredByNonEagerTypeMatching() { assertThat(!DummyFactory.wasPrototypeCreated()).as("prototype not instantiated").isTrue(); String[] beanNames = lbf.getBeanNamesForType(TestBean.class, true, false); - assertThat(beanNames.length).isEqualTo(0); + assertThat(beanNames).hasSize(0); beanNames = lbf.getBeanNamesForAnnotation(SuppressWarnings.class); - assertThat(beanNames.length).isEqualTo(0); + assertThat(beanNames).hasSize(0); assertThat(lbf.containsSingleton("x1")).isFalse(); assertThat(lbf.containsBean("x1")).isTrue(); @@ -283,7 +283,7 @@ void initializedFactoryBeanFoundByNonEagerTypeMatching() { assertThat(!DummyFactory.wasPrototypeCreated()).as("prototype not instantiated").isTrue(); String[] beanNames = lbf.getBeanNamesForType(TestBean.class, true, false); - assertThat(beanNames.length).isEqualTo(1); + assertThat(beanNames).hasSize(1); assertThat(beanNames[0]).isEqualTo("x1"); assertThat(lbf.containsSingleton("x1")).isTrue(); assertThat(lbf.containsBean("x1")).isTrue(); @@ -337,7 +337,7 @@ void staticFactoryMethodFoundByNonEagerTypeMatching() { TestBeanFactory.initialized = false; String[] beanNames = lbf.getBeanNamesForType(TestBean.class, true, false); - assertThat(beanNames.length).isEqualTo(1); + assertThat(beanNames).hasSize(1); assertThat(beanNames[0]).isEqualTo("x1"); assertThat(lbf.containsSingleton("x1")).isFalse(); assertThat(lbf.containsBean("x1")).isTrue(); @@ -349,7 +349,7 @@ void staticFactoryMethodFoundByNonEagerTypeMatching() { assertThat(lbf.isTypeMatch("x1", TestBean.class)).isTrue(); assertThat(lbf.isTypeMatch("&x1", TestBean.class)).isFalse(); assertThat(lbf.getType("x1")).isEqualTo(TestBean.class); - assertThat(lbf.getType("&x1")).isEqualTo(null); + assertThat(lbf.getType("&x1")).isNull(); assertThat(TestBeanFactory.initialized).isFalse(); } @@ -362,7 +362,7 @@ void staticPrototypeFactoryMethodFoundByNonEagerTypeMatching() { TestBeanFactory.initialized = false; String[] beanNames = lbf.getBeanNamesForType(TestBean.class, true, false); - assertThat(beanNames.length).isEqualTo(1); + assertThat(beanNames).hasSize(1); assertThat(beanNames[0]).isEqualTo("x1"); assertThat(lbf.containsSingleton("x1")).isFalse(); assertThat(lbf.containsBean("x1")).isTrue(); @@ -374,7 +374,7 @@ void staticPrototypeFactoryMethodFoundByNonEagerTypeMatching() { assertThat(lbf.isTypeMatch("x1", TestBean.class)).isTrue(); assertThat(lbf.isTypeMatch("&x1", TestBean.class)).isFalse(); assertThat(lbf.getType("x1")).isEqualTo(TestBean.class); - assertThat(lbf.getType("&x1")).isEqualTo(null); + assertThat(lbf.getType("&x1")).isNull(); assertThat(TestBeanFactory.initialized).isFalse(); } @@ -389,7 +389,7 @@ void nonStaticFactoryMethodFoundByNonEagerTypeMatching() { TestBeanFactory.initialized = false; String[] beanNames = lbf.getBeanNamesForType(TestBean.class, true, false); - assertThat(beanNames.length).isEqualTo(1); + assertThat(beanNames).hasSize(1); assertThat(beanNames[0]).isEqualTo("x1"); assertThat(lbf.containsSingleton("x1")).isFalse(); assertThat(lbf.containsBean("x1")).isTrue(); @@ -401,7 +401,7 @@ void nonStaticFactoryMethodFoundByNonEagerTypeMatching() { assertThat(lbf.isTypeMatch("x1", TestBean.class)).isTrue(); assertThat(lbf.isTypeMatch("&x1", TestBean.class)).isFalse(); assertThat(lbf.getType("x1")).isEqualTo(TestBean.class); - assertThat(lbf.getType("&x1")).isEqualTo(null); + assertThat(lbf.getType("&x1")).isNull(); assertThat(TestBeanFactory.initialized).isFalse(); } @@ -417,7 +417,7 @@ void nonStaticPrototypeFactoryMethodFoundByNonEagerTypeMatching() { TestBeanFactory.initialized = false; String[] beanNames = lbf.getBeanNamesForType(TestBean.class, true, false); - assertThat(beanNames.length).isEqualTo(1); + assertThat(beanNames).hasSize(1); assertThat(beanNames[0]).isEqualTo("x1"); assertThat(lbf.containsSingleton("x1")).isFalse(); assertThat(lbf.containsBean("x1")).isTrue(); @@ -450,7 +450,7 @@ void nonStaticPrototypeFactoryMethodFoundByNonEagerTypeMatching() { assertThat(lbf.isTypeMatch("x2", Object.class)).isTrue(); assertThat(lbf.isTypeMatch("&x2", Object.class)).isFalse(); assertThat(lbf.getType("x2")).isEqualTo(TestBean.class); - assertThat(lbf.getType("&x2")).isEqualTo(null); + assertThat(lbf.getType("&x2")).isNull(); assertThat(lbf.getAliases("x1").length).isEqualTo(1); assertThat(lbf.getAliases("x1")[0]).isEqualTo("x2"); assertThat(lbf.getAliases("&x1").length).isEqualTo(1); @@ -3030,7 +3030,7 @@ public CustomTypeConverter(NumberFormat numberFormat) { public Object convertIfNecessary(Object value, @Nullable Class requiredType) { if (value instanceof String && Float.class.isAssignableFrom(requiredType)) { try { - return new Float(this.numberFormat.parse((String) value).floatValue()); + return this.numberFormat.parse((String) value).floatValue(); } catch (ParseException ex) { throw new TypeMismatchException(value, requiredType, ex); diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/support/BeanFactoryGenericsTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/support/BeanFactoryGenericsTests.java index e3ba7b5d93f1..5a981f91e54c 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/support/BeanFactoryGenericsTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/support/BeanFactoryGenericsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -64,10 +64,10 @@ * @author Sam Brannen * @since 20.01.2006 */ -public class BeanFactoryGenericsTests { +class BeanFactoryGenericsTests { @Test - public void testGenericSetProperty() { + void testGenericSetProperty() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); @@ -84,7 +84,7 @@ public void testGenericSetProperty() { } @Test - public void testGenericListProperty() throws Exception { + void testGenericListProperty() throws Exception { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); @@ -101,7 +101,7 @@ public void testGenericListProperty() throws Exception { } @Test - public void testGenericListPropertyWithAutowiring() throws Exception { + void testGenericListPropertyWithAutowiring() throws Exception { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); bf.registerSingleton("resource1", new UrlResource("http://localhost:8080")); bf.registerSingleton("resource2", new UrlResource("http://localhost:9090")); @@ -116,7 +116,7 @@ public void testGenericListPropertyWithAutowiring() throws Exception { } @Test - public void testGenericListPropertyWithInvalidElementType() { + void testGenericListPropertyWithInvalidElementType() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); RootBeanDefinition rbd = new RootBeanDefinition(GenericIntegerBean.class); @@ -134,7 +134,7 @@ public void testGenericListPropertyWithInvalidElementType() { } @Test - public void testGenericListPropertyWithOptionalAutowiring() { + void testGenericListPropertyWithOptionalAutowiring() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); @@ -146,7 +146,7 @@ public void testGenericListPropertyWithOptionalAutowiring() { } @Test - public void testGenericMapProperty() { + void testGenericMapProperty() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); @@ -158,12 +158,12 @@ public void testGenericMapProperty() { bf.registerBeanDefinition("genericBean", rbd); GenericBean gb = (GenericBean) bf.getBean("genericBean"); - assertThat(gb.getShortMap().get(new Short("4"))).isEqualTo(5); - assertThat(gb.getShortMap().get(new Short("6"))).isEqualTo(7); + assertThat(gb.getShortMap().get(Short.valueOf("4"))).isEqualTo(5); + assertThat(gb.getShortMap().get(Short.valueOf("6"))).isEqualTo(7); } @Test - public void testGenericListOfArraysProperty() { + void testGenericListOfArraysProperty() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); new XmlBeanDefinitionReader(bf).loadBeanDefinitions( new ClassPathResource("genericBeanTests.xml", getClass())); @@ -171,14 +171,14 @@ public void testGenericListOfArraysProperty() { assertThat(gb.getListOfArrays().size()).isEqualTo(1); String[] array = gb.getListOfArrays().get(0); - assertThat(array.length).isEqualTo(2); + assertThat(array).hasSize(2); assertThat(array[0]).isEqualTo("value1"); assertThat(array[1]).isEqualTo("value2"); } @Test - public void testGenericSetConstructor() { + void testGenericSetConstructor() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); @@ -195,7 +195,7 @@ public void testGenericSetConstructor() { } @Test - public void testGenericSetConstructorWithAutowiring() { + void testGenericSetConstructorWithAutowiring() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); bf.registerSingleton("integer1", 4); bf.registerSingleton("integer2", 5); @@ -210,7 +210,7 @@ public void testGenericSetConstructorWithAutowiring() { } @Test - public void testGenericSetConstructorWithOptionalAutowiring() { + void testGenericSetConstructorWithOptionalAutowiring() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); @@ -222,7 +222,7 @@ public void testGenericSetConstructorWithOptionalAutowiring() { } @Test - public void testGenericSetListConstructor() throws Exception { + void testGenericSetListConstructor() throws Exception { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); @@ -245,7 +245,7 @@ public void testGenericSetListConstructor() throws Exception { } @Test - public void testGenericSetListConstructorWithAutowiring() throws Exception { + void testGenericSetListConstructorWithAutowiring() throws Exception { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); bf.registerSingleton("integer1", 4); bf.registerSingleton("integer2", 5); @@ -264,7 +264,7 @@ public void testGenericSetListConstructorWithAutowiring() throws Exception { } @Test - public void testGenericSetListConstructorWithOptionalAutowiring() throws Exception { + void testGenericSetListConstructorWithOptionalAutowiring() throws Exception { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); bf.registerSingleton("resource1", new UrlResource("http://localhost:8080")); bf.registerSingleton("resource2", new UrlResource("http://localhost:9090")); @@ -279,7 +279,7 @@ public void testGenericSetListConstructorWithOptionalAutowiring() throws Excepti } @Test - public void testGenericSetMapConstructor() { + void testGenericSetMapConstructor() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); @@ -297,12 +297,12 @@ public void testGenericSetMapConstructor() { assertThat(gb.getIntegerSet().contains(4)).isTrue(); assertThat(gb.getIntegerSet().contains(5)).isTrue(); - assertThat(gb.getShortMap().get(new Short("4"))).isEqualTo(5); - assertThat(gb.getShortMap().get(new Short("6"))).isEqualTo(7); + assertThat(gb.getShortMap().get(Short.valueOf("4"))).isEqualTo(5); + assertThat(gb.getShortMap().get(Short.valueOf("6"))).isEqualTo(7); } @Test - public void testGenericMapResourceConstructor() throws Exception { + void testGenericMapResourceConstructor() throws Exception { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); @@ -315,13 +315,13 @@ public void testGenericMapResourceConstructor() throws Exception { bf.registerBeanDefinition("genericBean", rbd); GenericBean gb = (GenericBean) bf.getBean("genericBean"); - assertThat(gb.getShortMap().get(new Short("4"))).isEqualTo(5); - assertThat(gb.getShortMap().get(new Short("6"))).isEqualTo(7); + assertThat(gb.getShortMap().get(Short.valueOf("4"))).isEqualTo(5); + assertThat(gb.getShortMap().get(Short.valueOf("6"))).isEqualTo(7); assertThat(gb.getResourceList().get(0)).isEqualTo(new UrlResource("http://localhost:8080")); } @Test - public void testGenericMapMapConstructor() { + void testGenericMapMapConstructor() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); @@ -338,16 +338,16 @@ public void testGenericMapMapConstructor() { GenericBean gb = (GenericBean) bf.getBean("genericBean"); assertThat(gb.getShortMap()).isNotSameAs(gb.getPlainMap()); - assertThat(gb.getPlainMap().size()).isEqualTo(2); + assertThat(gb.getPlainMap()).hasSize(2); assertThat(gb.getPlainMap().get("1")).isEqualTo("0"); assertThat(gb.getPlainMap().get("2")).isEqualTo("3"); assertThat(gb.getShortMap().size()).isEqualTo(2); - assertThat(gb.getShortMap().get(new Short("4"))).isEqualTo(5); - assertThat(gb.getShortMap().get(new Short("6"))).isEqualTo(7); + assertThat(gb.getShortMap().get(Short.valueOf("4"))).isEqualTo(5); + assertThat(gb.getShortMap().get(Short.valueOf("6"))).isEqualTo(7); } @Test - public void testGenericMapMapConstructorWithSameRefAndConversion() { + void testGenericMapMapConstructorWithSameRefAndConversion() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); @@ -361,22 +361,22 @@ public void testGenericMapMapConstructorWithSameRefAndConversion() { GenericBean gb = (GenericBean) bf.getBean("genericBean"); assertThat(gb.getShortMap()).isNotSameAs(gb.getPlainMap()); - assertThat(gb.getPlainMap().size()).isEqualTo(2); + assertThat(gb.getPlainMap()).hasSize(2); assertThat(gb.getPlainMap().get("1")).isEqualTo("0"); assertThat(gb.getPlainMap().get("2")).isEqualTo("3"); assertThat(gb.getShortMap().size()).isEqualTo(2); - assertThat(gb.getShortMap().get(new Short("1"))).isEqualTo(0); - assertThat(gb.getShortMap().get(new Short("2"))).isEqualTo(3); + assertThat(gb.getShortMap().get(Short.valueOf("1"))).isEqualTo(0); + assertThat(gb.getShortMap().get(Short.valueOf("2"))).isEqualTo(3); } @Test - public void testGenericMapMapConstructorWithSameRefAndNoConversion() { + void testGenericMapMapConstructorWithSameRefAndNoConversion() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); Map input = new HashMap<>(); - input.put(new Short((short) 1), 0); - input.put(new Short((short) 2), 3); + input.put((short) 1, 0); + input.put((short) 2, 3); rbd.getConstructorArgumentValues().addGenericArgumentValue(input); rbd.getConstructorArgumentValues().addGenericArgumentValue(input); @@ -384,13 +384,13 @@ public void testGenericMapMapConstructorWithSameRefAndNoConversion() { GenericBean gb = (GenericBean) bf.getBean("genericBean"); assertThat(gb.getShortMap()).isSameAs(gb.getPlainMap()); - assertThat(gb.getShortMap().size()).isEqualTo(2); - assertThat(gb.getShortMap().get(new Short("1"))).isEqualTo(0); - assertThat(gb.getShortMap().get(new Short("2"))).isEqualTo(3); + assertThat(gb.getShortMap()).hasSize(2); + assertThat(gb.getShortMap().get(Short.valueOf("1"))).isEqualTo(0); + assertThat(gb.getShortMap().get(Short.valueOf("2"))).isEqualTo(3); } @Test - public void testGenericMapWithKeyTypeConstructor() { + void testGenericMapWithKeyTypeConstructor() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); @@ -407,7 +407,7 @@ public void testGenericMapWithKeyTypeConstructor() { } @Test - public void testGenericMapWithCollectionValueConstructor() { + void testGenericMapWithCollectionValueConstructor() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); bf.addPropertyEditorRegistrar(new PropertyEditorRegistrar() { @Override @@ -438,7 +438,7 @@ public void registerCustomEditors(PropertyEditorRegistry registry) { @Test - public void testGenericSetFactoryMethod() { + void testGenericSetFactoryMethod() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); rbd.setFactoryMethodName("createInstance"); @@ -456,7 +456,7 @@ public void testGenericSetFactoryMethod() { } @Test - public void testGenericSetListFactoryMethod() throws Exception { + void testGenericSetListFactoryMethod() throws Exception { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); rbd.setFactoryMethodName("createInstance"); @@ -480,7 +480,7 @@ public void testGenericSetListFactoryMethod() throws Exception { } @Test - public void testGenericSetMapFactoryMethod() { + void testGenericSetMapFactoryMethod() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); rbd.setFactoryMethodName("createInstance"); @@ -499,12 +499,12 @@ public void testGenericSetMapFactoryMethod() { assertThat(gb.getIntegerSet().contains(4)).isTrue(); assertThat(gb.getIntegerSet().contains(5)).isTrue(); - assertThat(gb.getShortMap().get(new Short("4"))).isEqualTo(5); - assertThat(gb.getShortMap().get(new Short("6"))).isEqualTo(7); + assertThat(gb.getShortMap().get(Short.valueOf("4"))).isEqualTo(5); + assertThat(gb.getShortMap().get(Short.valueOf("6"))).isEqualTo(7); } @Test - public void testGenericMapResourceFactoryMethod() throws Exception { + void testGenericMapResourceFactoryMethod() throws Exception { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); rbd.setFactoryMethodName("createInstance"); @@ -518,13 +518,13 @@ public void testGenericMapResourceFactoryMethod() throws Exception { bf.registerBeanDefinition("genericBean", rbd); GenericBean gb = (GenericBean) bf.getBean("genericBean"); - assertThat(gb.getShortMap().get(new Short("4"))).isEqualTo(5); - assertThat(gb.getShortMap().get(new Short("6"))).isEqualTo(7); + assertThat(gb.getShortMap().get(Short.valueOf("4"))).isEqualTo(5); + assertThat(gb.getShortMap().get(Short.valueOf("6"))).isEqualTo(7); assertThat(gb.getResourceList().get(0)).isEqualTo(new UrlResource("http://localhost:8080")); } @Test - public void testGenericMapMapFactoryMethod() { + void testGenericMapMapFactoryMethod() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); rbd.setFactoryMethodName("createInstance"); @@ -543,12 +543,12 @@ public void testGenericMapMapFactoryMethod() { assertThat(gb.getPlainMap().get("1")).isEqualTo("0"); assertThat(gb.getPlainMap().get("2")).isEqualTo("3"); - assertThat(gb.getShortMap().get(new Short("4"))).isEqualTo(5); - assertThat(gb.getShortMap().get(new Short("6"))).isEqualTo(7); + assertThat(gb.getShortMap().get(Short.valueOf("4"))).isEqualTo(5); + assertThat(gb.getShortMap().get(Short.valueOf("6"))).isEqualTo(7); } @Test - public void testGenericMapWithKeyTypeFactoryMethod() { + void testGenericMapWithKeyTypeFactoryMethod() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); RootBeanDefinition rbd = new RootBeanDefinition(GenericBean.class); rbd.setFactoryMethodName("createInstance"); @@ -561,12 +561,12 @@ public void testGenericMapWithKeyTypeFactoryMethod() { bf.registerBeanDefinition("genericBean", rbd); GenericBean gb = (GenericBean) bf.getBean("genericBean"); - assertThat(gb.getLongMap().get(new Long("4"))).isEqualTo("5"); - assertThat(gb.getLongMap().get(new Long("6"))).isEqualTo("7"); + assertThat(gb.getLongMap().get(Long.valueOf("4"))).isEqualTo("5"); + assertThat(gb.getLongMap().get(Long.valueOf("6"))).isEqualTo("7"); } @Test - public void testGenericMapWithCollectionValueFactoryMethod() { + void testGenericMapWithCollectionValueFactoryMethod() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); bf.addPropertyEditorRegistrar(new PropertyEditorRegistrar() { @Override @@ -597,7 +597,7 @@ public void registerCustomEditors(PropertyEditorRegistry registry) { } @Test - public void testGenericListBean() throws Exception { + void testGenericListBean() throws Exception { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); new XmlBeanDefinitionReader(bf).loadBeanDefinitions( new ClassPathResource("genericBeanTests.xml", getClass())); @@ -607,7 +607,7 @@ public void testGenericListBean() throws Exception { } @Test - public void testGenericSetBean() throws Exception { + void testGenericSetBean() throws Exception { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); new XmlBeanDefinitionReader(bf).loadBeanDefinitions( new ClassPathResource("genericBeanTests.xml", getClass())); @@ -617,18 +617,18 @@ public void testGenericSetBean() throws Exception { } @Test - public void testGenericMapBean() throws Exception { + void testGenericMapBean() throws Exception { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); new XmlBeanDefinitionReader(bf).loadBeanDefinitions( new ClassPathResource("genericBeanTests.xml", getClass())); Map map = (Map) bf.getBean("map"); - assertThat(map.size()).isEqualTo(1); + assertThat(map).hasSize(1); assertThat(map.keySet().iterator().next()).isEqualTo(10); assertThat(map.values().iterator().next()).isEqualTo(new URL("http://localhost:8080")); } @Test - public void testGenericallyTypedIntegerBean() { + void testGenericallyTypedIntegerBean() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); new XmlBeanDefinitionReader(bf).loadBeanDefinitions( new ClassPathResource("genericBeanTests.xml", getClass())); @@ -639,7 +639,7 @@ public void testGenericallyTypedIntegerBean() { } @Test - public void testGenericallyTypedSetOfIntegerBean() { + void testGenericallyTypedSetOfIntegerBean() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); new XmlBeanDefinitionReader(bf).loadBeanDefinitions( new ClassPathResource("genericBeanTests.xml", getClass())); @@ -651,7 +651,7 @@ public void testGenericallyTypedSetOfIntegerBean() { @Test @EnabledForTestGroups(LONG_RUNNING) - public void testSetBean() throws Exception { + void testSetBean() throws Exception { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); new XmlBeanDefinitionReader(bf).loadBeanDefinitions( new ClassPathResource("genericBeanTests.xml", getClass())); @@ -671,7 +671,7 @@ public void testSetBean() throws Exception { *

See SPR-9493 */ @Test - public void parameterizedStaticFactoryMethod() { + void parameterizedStaticFactoryMethod() { RootBeanDefinition rbd = new RootBeanDefinition(Mockito.class); rbd.setFactoryMethodName("mock"); rbd.getConstructorArgumentValues().addGenericArgumentValue(Runnable.class); @@ -682,7 +682,7 @@ public void parameterizedStaticFactoryMethod() { assertThat(bf.getType("mock")).isEqualTo(Runnable.class); assertThat(bf.getType("mock")).isEqualTo(Runnable.class); Map beans = bf.getBeansOfType(Runnable.class); - assertThat(beans.size()).isEqualTo(1); + assertThat(beans).hasSize(1); } /** @@ -697,7 +697,7 @@ public void parameterizedStaticFactoryMethod() { *

See SPR-10411 */ @Test - public void parameterizedInstanceFactoryMethod() { + void parameterizedInstanceFactoryMethod() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); RootBeanDefinition rbd = new RootBeanDefinition(MocksControl.class); @@ -714,11 +714,11 @@ public void parameterizedInstanceFactoryMethod() { assertThat(bf.getType("mock")).isEqualTo(Runnable.class); assertThat(bf.getType("mock")).isEqualTo(Runnable.class); Map beans = bf.getBeansOfType(Runnable.class); - assertThat(beans.size()).isEqualTo(1); + assertThat(beans).hasSize(1); } @Test - public void parameterizedInstanceFactoryMethodWithNonResolvedClassName() { + void parameterizedInstanceFactoryMethodWithNonResolvedClassName() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); RootBeanDefinition rbd = new RootBeanDefinition(MocksControl.class); @@ -735,11 +735,11 @@ public void parameterizedInstanceFactoryMethodWithNonResolvedClassName() { assertThat(bf.getType("mock")).isEqualTo(Runnable.class); assertThat(bf.getType("mock")).isEqualTo(Runnable.class); Map beans = bf.getBeansOfType(Runnable.class); - assertThat(beans.size()).isEqualTo(1); + assertThat(beans).hasSize(1); } @Test - public void parameterizedInstanceFactoryMethodWithWrappedClassName() { + void parameterizedInstanceFactoryMethodWithWrappedClassName() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); RootBeanDefinition rbd = new RootBeanDefinition(); @@ -754,11 +754,11 @@ public void parameterizedInstanceFactoryMethodWithWrappedClassName() { assertThat(bf.getType("mock")).isEqualTo(Runnable.class); assertThat(bf.getType("mock")).isEqualTo(Runnable.class); Map beans = bf.getBeansOfType(Runnable.class); - assertThat(beans.size()).isEqualTo(1); + assertThat(beans).hasSize(1); } @Test - public void parameterizedInstanceFactoryMethodWithInvalidClassName() { + void parameterizedInstanceFactoryMethodWithInvalidClassName() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); RootBeanDefinition rbd = new RootBeanDefinition(MocksControl.class); @@ -775,11 +775,11 @@ public void parameterizedInstanceFactoryMethodWithInvalidClassName() { assertThat(bf.getType("mock")).isNull(); assertThat(bf.getType("mock")).isNull(); Map beans = bf.getBeansOfType(Runnable.class); - assertThat(beans.size()).isEqualTo(0); + assertThat(beans).hasSize(0); } @Test - public void parameterizedInstanceFactoryMethodWithIndexedArgument() { + void parameterizedInstanceFactoryMethodWithIndexedArgument() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); RootBeanDefinition rbd = new RootBeanDefinition(MocksControl.class); @@ -796,11 +796,11 @@ public void parameterizedInstanceFactoryMethodWithIndexedArgument() { assertThat(bf.getType("mock")).isEqualTo(Runnable.class); assertThat(bf.getType("mock")).isEqualTo(Runnable.class); Map beans = bf.getBeansOfType(Runnable.class); - assertThat(beans.size()).isEqualTo(1); + assertThat(beans).hasSize(1); } @Test // SPR-16720 - public void parameterizedInstanceFactoryMethodWithTempClassLoader() { + void parameterizedInstanceFactoryMethodWithTempClassLoader() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); bf.setTempClassLoader(new OverridingClassLoader(getClass().getClassLoader())); @@ -818,11 +818,11 @@ public void parameterizedInstanceFactoryMethodWithTempClassLoader() { assertThat(bf.getType("mock")).isEqualTo(Runnable.class); assertThat(bf.getType("mock")).isEqualTo(Runnable.class); Map beans = bf.getBeansOfType(Runnable.class); - assertThat(beans.size()).isEqualTo(1); + assertThat(beans).hasSize(1); } @Test - public void testGenericMatchingWithBeanNameDifferentiation() { + void testGenericMatchingWithBeanNameDifferentiation() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); bf.setAutowireCandidateResolver(new GenericTypeAwareAutowireCandidateResolver()); @@ -838,15 +838,15 @@ public void testGenericMatchingWithBeanNameDifferentiation() { String[] numberStoreNames = bf.getBeanNamesForType(ResolvableType.forClass(NumberStore.class)); String[] doubleStoreNames = bf.getBeanNamesForType(ResolvableType.forClassWithGenerics(NumberStore.class, Double.class)); String[] floatStoreNames = bf.getBeanNamesForType(ResolvableType.forClassWithGenerics(NumberStore.class, Float.class)); - assertThat(numberStoreNames.length).isEqualTo(2); + assertThat(numberStoreNames).hasSize(2); assertThat(numberStoreNames[0]).isEqualTo("doubleStore"); assertThat(numberStoreNames[1]).isEqualTo("floatStore"); - assertThat(doubleStoreNames.length).isEqualTo(0); - assertThat(floatStoreNames.length).isEqualTo(0); + assertThat(doubleStoreNames).hasSize(0); + assertThat(floatStoreNames).hasSize(0); } @Test - public void testGenericMatchingWithFullTypeDifferentiation() { + void testGenericMatchingWithFullTypeDifferentiation() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); bf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); bf.setAutowireCandidateResolver(new GenericTypeAwareAutowireCandidateResolver()); @@ -867,12 +867,12 @@ public void testGenericMatchingWithFullTypeDifferentiation() { String[] numberStoreNames = bf.getBeanNamesForType(ResolvableType.forClass(NumberStore.class)); String[] doubleStoreNames = bf.getBeanNamesForType(ResolvableType.forClassWithGenerics(NumberStore.class, Double.class)); String[] floatStoreNames = bf.getBeanNamesForType(ResolvableType.forClassWithGenerics(NumberStore.class, Float.class)); - assertThat(numberStoreNames.length).isEqualTo(2); + assertThat(numberStoreNames).hasSize(2); assertThat(numberStoreNames[0]).isEqualTo("store1"); assertThat(numberStoreNames[1]).isEqualTo("store2"); - assertThat(doubleStoreNames.length).isEqualTo(1); + assertThat(doubleStoreNames).hasSize(1); assertThat(doubleStoreNames[0]).isEqualTo("store1"); - assertThat(floatStoreNames.length).isEqualTo(1); + assertThat(floatStoreNames).hasSize(1); assertThat(floatStoreNames[0]).isEqualTo("store2"); ObjectProvider> numberStoreProvider = bf.getBeanProvider(ResolvableType.forClass(NumberStore.class)); @@ -938,7 +938,7 @@ public void testGenericMatchingWithFullTypeDifferentiation() { } @Test - public void testGenericMatchingWithUnresolvedOrderedStream() { + void testGenericMatchingWithUnresolvedOrderedStream() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); bf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); bf.setAutowireCandidateResolver(new GenericTypeAwareAutowireCandidateResolver()); diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/wiring/ClassNameBeanWiringInfoResolverTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/wiring/ClassNameBeanWiringInfoResolverTests.java index 67cef6f11665..becb7961f2a3 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/wiring/ClassNameBeanWiringInfoResolverTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/wiring/ClassNameBeanWiringInfoResolverTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -26,18 +26,18 @@ * * @author Rick Evans */ -public class ClassNameBeanWiringInfoResolverTests { +class ClassNameBeanWiringInfoResolverTests { @Test - public void resolveWiringInfoWithNullBeanInstance() throws Exception { + void resolveWiringInfoWithNullBeanInstance() throws Exception { assertThatIllegalArgumentException().isThrownBy(() -> new ClassNameBeanWiringInfoResolver().resolveWiringInfo(null)); } @Test - public void resolveWiringInfo() { + void resolveWiringInfo() { ClassNameBeanWiringInfoResolver resolver = new ClassNameBeanWiringInfoResolver(); - Long beanInstance = new Long(1); + Long beanInstance = 1L; BeanWiringInfo info = resolver.resolveWiringInfo(beanInstance); assertThat(info).isNotNull(); assertThat(info.getBeanName()).as("Not resolving bean name to the class name of the supplied bean instance as per class contract.").isEqualTo(beanInstance.getClass().getName()); diff --git a/spring-beans/src/test/java/org/springframework/beans/propertyeditors/CustomEditorTests.java b/spring-beans/src/test/java/org/springframework/beans/propertyeditors/CustomEditorTests.java index 0de98a10f002..e3dddf62db2e 100644 --- a/spring-beans/src/test/java/org/springframework/beans/propertyeditors/CustomEditorTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/propertyeditors/CustomEditorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -64,10 +64,10 @@ * @author Chris Beams * @since 10.06.2003 */ -public class CustomEditorTests { +class CustomEditorTests { @Test - public void testComplexObject() { + void testComplexObject() { TestBean tb = new TestBean(); String newName = "Rod"; String tbString = "Kerry_34"; @@ -80,12 +80,12 @@ public void testComplexObject() { pvs.addPropertyValue(new PropertyValue("touchy", "valid")); pvs.addPropertyValue(new PropertyValue("spouse", tbString)); bw.setPropertyValues(pvs); - assertThat(tb.getSpouse() != null).as("spouse is non-null").isTrue(); + assertThat(tb.getSpouse()).as("spouse is non-null").isNotNull(); assertThat(tb.getSpouse().getName().equals("Kerry") && tb.getSpouse().getAge() == 34).as("spouse name is Kerry and age is 34").isTrue(); } @Test - public void testComplexObjectWithOldValueAccess() { + void testComplexObjectWithOldValueAccess() { TestBean tb = new TestBean(); String newName = "Rod"; String tbString = "Kerry_34"; @@ -100,7 +100,7 @@ public void testComplexObjectWithOldValueAccess() { pvs.addPropertyValue(new PropertyValue("spouse", tbString)); bw.setPropertyValues(pvs); - assertThat(tb.getSpouse() != null).as("spouse is non-null").isTrue(); + assertThat(tb.getSpouse()).as("spouse is non-null").isNotNull(); assertThat(tb.getSpouse().getName().equals("Kerry") && tb.getSpouse().getAge() == 34).as("spouse name is Kerry and age is 34").isTrue(); ITestBean spouse = tb.getSpouse(); @@ -109,7 +109,7 @@ public void testComplexObjectWithOldValueAccess() { } @Test - public void testCustomEditorForSingleProperty() { + void testCustomEditorForSingleProperty() { TestBean tb = new TestBean(); BeanWrapper bw = new BeanWrapperImpl(tb); bw.registerCustomEditor(String.class, "name", new PropertyEditorSupport() { @@ -127,7 +127,7 @@ public void setAsText(String text) throws IllegalArgumentException { } @Test - public void testCustomEditorForAllStringProperties() { + void testCustomEditorForAllStringProperties() { TestBean tb = new TestBean(); BeanWrapper bw = new BeanWrapperImpl(tb); bw.registerCustomEditor(String.class, new PropertyEditorSupport() { @@ -145,7 +145,7 @@ public void setAsText(String text) throws IllegalArgumentException { } @Test - public void testCustomEditorForSingleNestedProperty() { + void testCustomEditorForSingleNestedProperty() { TestBean tb = new TestBean(); tb.setSpouse(new TestBean()); BeanWrapper bw = new BeanWrapperImpl(tb); @@ -164,7 +164,7 @@ public void setAsText(String text) throws IllegalArgumentException { } @Test - public void testCustomEditorForAllNestedStringProperties() { + void testCustomEditorForAllNestedStringProperties() { TestBean tb = new TestBean(); tb.setSpouse(new TestBean()); BeanWrapper bw = new BeanWrapperImpl(tb); @@ -183,7 +183,7 @@ public void setAsText(String text) throws IllegalArgumentException { } @Test - public void testDefaultBooleanEditorForPrimitiveType() { + void testDefaultBooleanEditorForPrimitiveType() { BooleanTestBean tb = new BooleanTestBean(); BeanWrapper bw = new BeanWrapperImpl(tb); @@ -229,7 +229,7 @@ public void testDefaultBooleanEditorForPrimitiveType() { } @Test - public void testDefaultBooleanEditorForWrapperType() { + void testDefaultBooleanEditorForWrapperType() { BooleanTestBean tb = new BooleanTestBean(); BeanWrapper bw = new BeanWrapperImpl(tb); @@ -239,28 +239,28 @@ public void testDefaultBooleanEditorForWrapperType() { bw.setPropertyValue("bool2", "false"); assertThat(Boolean.FALSE.equals(bw.getPropertyValue("bool2"))).as("Correct bool2 value").isTrue(); - boolean condition3 = !tb.getBool2().booleanValue(); + boolean condition3 = !tb.getBool2(); assertThat(condition3).as("Correct bool2 value").isTrue(); bw.setPropertyValue("bool2", "on"); assertThat(tb.getBool2().booleanValue()).as("Correct bool2 value").isTrue(); bw.setPropertyValue("bool2", "off"); - boolean condition2 = !tb.getBool2().booleanValue(); + boolean condition2 = !tb.getBool2(); assertThat(condition2).as("Correct bool2 value").isTrue(); bw.setPropertyValue("bool2", "yes"); assertThat(tb.getBool2().booleanValue()).as("Correct bool2 value").isTrue(); bw.setPropertyValue("bool2", "no"); - boolean condition1 = !tb.getBool2().booleanValue(); + boolean condition1 = !tb.getBool2(); assertThat(condition1).as("Correct bool2 value").isTrue(); bw.setPropertyValue("bool2", "1"); assertThat(tb.getBool2().booleanValue()).as("Correct bool2 value").isTrue(); bw.setPropertyValue("bool2", "0"); - boolean condition = !tb.getBool2().booleanValue(); + boolean condition = !tb.getBool2(); assertThat(condition).as("Correct bool2 value").isTrue(); bw.setPropertyValue("bool2", ""); @@ -268,7 +268,7 @@ public void testDefaultBooleanEditorForWrapperType() { } @Test - public void testCustomBooleanEditorWithAllowEmpty() { + void testCustomBooleanEditorWithAllowEmpty() { BooleanTestBean tb = new BooleanTestBean(); BeanWrapper bw = new BeanWrapperImpl(tb); bw.registerCustomEditor(Boolean.class, new CustomBooleanEditor(true)); @@ -279,37 +279,37 @@ public void testCustomBooleanEditorWithAllowEmpty() { bw.setPropertyValue("bool2", "false"); assertThat(Boolean.FALSE.equals(bw.getPropertyValue("bool2"))).as("Correct bool2 value").isTrue(); - boolean condition3 = !tb.getBool2().booleanValue(); + boolean condition3 = !tb.getBool2(); assertThat(condition3).as("Correct bool2 value").isTrue(); bw.setPropertyValue("bool2", "on"); assertThat(tb.getBool2().booleanValue()).as("Correct bool2 value").isTrue(); bw.setPropertyValue("bool2", "off"); - boolean condition2 = !tb.getBool2().booleanValue(); + boolean condition2 = !tb.getBool2(); assertThat(condition2).as("Correct bool2 value").isTrue(); bw.setPropertyValue("bool2", "yes"); assertThat(tb.getBool2().booleanValue()).as("Correct bool2 value").isTrue(); bw.setPropertyValue("bool2", "no"); - boolean condition1 = !tb.getBool2().booleanValue(); + boolean condition1 = !tb.getBool2(); assertThat(condition1).as("Correct bool2 value").isTrue(); bw.setPropertyValue("bool2", "1"); assertThat(tb.getBool2().booleanValue()).as("Correct bool2 value").isTrue(); bw.setPropertyValue("bool2", "0"); - boolean condition = !tb.getBool2().booleanValue(); + boolean condition = !tb.getBool2(); assertThat(condition).as("Correct bool2 value").isTrue(); bw.setPropertyValue("bool2", ""); - assertThat(bw.getPropertyValue("bool2") == null).as("Correct bool2 value").isTrue(); - assertThat(tb.getBool2() == null).as("Correct bool2 value").isTrue(); + assertThat(bw.getPropertyValue("bool2")).as("Correct bool2 value").isNull(); + assertThat(tb.getBool2()).as("Correct bool2 value").isNull(); } @Test - public void testCustomBooleanEditorWithSpecialTrueAndFalseStrings() throws Exception { + void testCustomBooleanEditorWithSpecialTrueAndFalseStrings() throws Exception { String trueString = "pechorin"; String falseString = "nash"; @@ -333,7 +333,7 @@ public void testCustomBooleanEditorWithSpecialTrueAndFalseStrings() throws Excep } @Test - public void testDefaultNumberEditor() { + void testDefaultNumberEditor() { NumberTestBean tb = new NumberTestBean(); BeanWrapper bw = new BeanWrapperImpl(tb); @@ -350,34 +350,34 @@ public void testDefaultNumberEditor() { bw.setPropertyValue("double2", "6.1"); bw.setPropertyValue("bigDecimal", "4.5"); - assertThat(new Short("1").equals(bw.getPropertyValue("short1"))).as("Correct short1 value").isTrue(); + assertThat(Short.valueOf("1").equals(bw.getPropertyValue("short1"))).as("Correct short1 value").isTrue(); assertThat(tb.getShort1() == 1).as("Correct short1 value").isTrue(); - assertThat(new Short("2").equals(bw.getPropertyValue("short2"))).as("Correct short2 value").isTrue(); - assertThat(new Short("2").equals(tb.getShort2())).as("Correct short2 value").isTrue(); - assertThat(new Integer("7").equals(bw.getPropertyValue("int1"))).as("Correct int1 value").isTrue(); + assertThat(Short.valueOf("2").equals(bw.getPropertyValue("short2"))).as("Correct short2 value").isTrue(); + assertThat(Short.valueOf("2").equals(tb.getShort2())).as("Correct short2 value").isTrue(); + assertThat(Integer.valueOf("7").equals(bw.getPropertyValue("int1"))).as("Correct int1 value").isTrue(); assertThat(tb.getInt1() == 7).as("Correct int1 value").isTrue(); - assertThat(new Integer("8").equals(bw.getPropertyValue("int2"))).as("Correct int2 value").isTrue(); - assertThat(new Integer("8").equals(tb.getInt2())).as("Correct int2 value").isTrue(); - assertThat(new Long("5").equals(bw.getPropertyValue("long1"))).as("Correct long1 value").isTrue(); + assertThat(Integer.valueOf("8").equals(bw.getPropertyValue("int2"))).as("Correct int2 value").isTrue(); + assertThat(Integer.valueOf("8").equals(tb.getInt2())).as("Correct int2 value").isTrue(); + assertThat(Long.valueOf("5").equals(bw.getPropertyValue("long1"))).as("Correct long1 value").isTrue(); assertThat(tb.getLong1() == 5).as("Correct long1 value").isTrue(); - assertThat(new Long("6").equals(bw.getPropertyValue("long2"))).as("Correct long2 value").isTrue(); - assertThat(new Long("6").equals(tb.getLong2())).as("Correct long2 value").isTrue(); + assertThat(Long.valueOf("6").equals(bw.getPropertyValue("long2"))).as("Correct long2 value").isTrue(); + assertThat(Long.valueOf("6").equals(tb.getLong2())).as("Correct long2 value").isTrue(); assertThat(new BigInteger("3").equals(bw.getPropertyValue("bigInteger"))).as("Correct bigInteger value").isTrue(); assertThat(new BigInteger("3").equals(tb.getBigInteger())).as("Correct bigInteger value").isTrue(); - assertThat(new Float("7.1").equals(bw.getPropertyValue("float1"))).as("Correct float1 value").isTrue(); - assertThat(new Float("7.1").equals(new Float(tb.getFloat1()))).as("Correct float1 value").isTrue(); - assertThat(new Float("8.1").equals(bw.getPropertyValue("float2"))).as("Correct float2 value").isTrue(); - assertThat(new Float("8.1").equals(tb.getFloat2())).as("Correct float2 value").isTrue(); - assertThat(new Double("5.1").equals(bw.getPropertyValue("double1"))).as("Correct double1 value").isTrue(); + assertThat(Float.valueOf("7.1").equals(bw.getPropertyValue("float1"))).as("Correct float1 value").isTrue(); + assertThat(Float.valueOf("7.1").equals(tb.getFloat1())).as("Correct float1 value").isTrue(); + assertThat(Float.valueOf("8.1").equals(bw.getPropertyValue("float2"))).as("Correct float2 value").isTrue(); + assertThat(Float.valueOf("8.1").equals(tb.getFloat2())).as("Correct float2 value").isTrue(); + assertThat(Double.valueOf("5.1").equals(bw.getPropertyValue("double1"))).as("Correct double1 value").isTrue(); assertThat(tb.getDouble1() == 5.1).as("Correct double1 value").isTrue(); - assertThat(new Double("6.1").equals(bw.getPropertyValue("double2"))).as("Correct double2 value").isTrue(); - assertThat(new Double("6.1").equals(tb.getDouble2())).as("Correct double2 value").isTrue(); + assertThat(Double.valueOf("6.1").equals(bw.getPropertyValue("double2"))).as("Correct double2 value").isTrue(); + assertThat(Double.valueOf("6.1").equals(tb.getDouble2())).as("Correct double2 value").isTrue(); assertThat(new BigDecimal("4.5").equals(bw.getPropertyValue("bigDecimal"))).as("Correct bigDecimal value").isTrue(); assertThat(new BigDecimal("4.5").equals(tb.getBigDecimal())).as("Correct bigDecimal value").isTrue(); } @Test - public void testCustomNumberEditorWithoutAllowEmpty() { + void testCustomNumberEditorWithoutAllowEmpty() { NumberFormat nf = NumberFormat.getNumberInstance(Locale.GERMAN); NumberTestBean tb = new NumberTestBean(); BeanWrapper bw = new BeanWrapperImpl(tb); @@ -407,34 +407,34 @@ public void testCustomNumberEditorWithoutAllowEmpty() { bw.setPropertyValue("double2", "6,1"); bw.setPropertyValue("bigDecimal", "4,5"); - assertThat(new Short("1").equals(bw.getPropertyValue("short1"))).as("Correct short1 value").isTrue(); + assertThat(bw.getPropertyValue("short1")).as("Correct short1 value").isEqualTo(Short.valueOf("1")); assertThat(tb.getShort1() == 1).as("Correct short1 value").isTrue(); - assertThat(new Short("2").equals(bw.getPropertyValue("short2"))).as("Correct short2 value").isTrue(); - assertThat(new Short("2").equals(tb.getShort2())).as("Correct short2 value").isTrue(); - assertThat(new Integer("7").equals(bw.getPropertyValue("int1"))).as("Correct int1 value").isTrue(); + assertThat(bw.getPropertyValue("short2")).as("Correct short2 value").isEqualTo(Short.valueOf("2")); + assertThat(tb.getShort2()).as("Correct short2 value").isEqualTo(Short.valueOf("2")); + assertThat(bw.getPropertyValue("int1")).as("Correct int1 value").isEqualTo(Integer.valueOf("7")); assertThat(tb.getInt1() == 7).as("Correct int1 value").isTrue(); - assertThat(new Integer("8").equals(bw.getPropertyValue("int2"))).as("Correct int2 value").isTrue(); - assertThat(new Integer("8").equals(tb.getInt2())).as("Correct int2 value").isTrue(); - assertThat(new Long("5").equals(bw.getPropertyValue("long1"))).as("Correct long1 value").isTrue(); + assertThat(bw.getPropertyValue("int2")).as("Correct int2 value").isEqualTo(Integer.valueOf("8")); + assertThat(tb.getInt2()).as("Correct int2 value").isEqualTo(Integer.valueOf("8")); + assertThat(bw.getPropertyValue("long1")).as("Correct long1 value").isEqualTo(Long.valueOf("5")); assertThat(tb.getLong1() == 5).as("Correct long1 value").isTrue(); - assertThat(new Long("6").equals(bw.getPropertyValue("long2"))).as("Correct long2 value").isTrue(); - assertThat(new Long("6").equals(tb.getLong2())).as("Correct long2 value").isTrue(); + assertThat(bw.getPropertyValue("long2")).as("Correct long2 value").isEqualTo(Long.valueOf("6")); + assertThat(tb.getLong2()).as("Correct long2 value").isEqualTo(Long.valueOf("6")); assertThat(new BigInteger("3").equals(bw.getPropertyValue("bigInteger"))).as("Correct bigInteger value").isTrue(); assertThat(new BigInteger("3").equals(tb.getBigInteger())).as("Correct bigInteger value").isTrue(); - assertThat(new Float("7.1").equals(bw.getPropertyValue("float1"))).as("Correct float1 value").isTrue(); - assertThat(new Float("7.1").equals(new Float(tb.getFloat1()))).as("Correct float1 value").isTrue(); - assertThat(new Float("8.1").equals(bw.getPropertyValue("float2"))).as("Correct float2 value").isTrue(); - assertThat(new Float("8.1").equals(tb.getFloat2())).as("Correct float2 value").isTrue(); - assertThat(new Double("5.1").equals(bw.getPropertyValue("double1"))).as("Correct double1 value").isTrue(); + assertThat(bw.getPropertyValue("float1")).as("Correct float1 value").isEqualTo(Float.valueOf("7.1")); + assertThat(Float.valueOf(tb.getFloat1())).as("Correct float1 value").isEqualTo(Float.valueOf("7.1")); + assertThat(bw.getPropertyValue("float2")).as("Correct float2 value").isEqualTo(Float.valueOf("8.1")); + assertThat(tb.getFloat2()).as("Correct float2 value").isEqualTo(Float.valueOf("8.1")); + assertThat(bw.getPropertyValue("double1")).as("Correct double1 value").isEqualTo(Double.valueOf("5.1")); assertThat(tb.getDouble1() == 5.1).as("Correct double1 value").isTrue(); - assertThat(new Double("6.1").equals(bw.getPropertyValue("double2"))).as("Correct double2 value").isTrue(); - assertThat(new Double("6.1").equals(tb.getDouble2())).as("Correct double2 value").isTrue(); + assertThat(bw.getPropertyValue("double2")).as("Correct double2 value").isEqualTo(Double.valueOf("6.1")); + assertThat(tb.getDouble2()).as("Correct double2 value").isEqualTo(Double.valueOf("6.1")); assertThat(new BigDecimal("4.5").equals(bw.getPropertyValue("bigDecimal"))).as("Correct bigDecimal value").isTrue(); assertThat(new BigDecimal("4.5").equals(tb.getBigDecimal())).as("Correct bigDecimal value").isTrue(); } @Test - public void testCustomNumberEditorWithAllowEmpty() { + void testCustomNumberEditorWithAllowEmpty() { NumberFormat nf = NumberFormat.getNumberInstance(Locale.GERMAN); NumberTestBean tb = new NumberTestBean(); BeanWrapper bw = new BeanWrapperImpl(tb); @@ -443,10 +443,10 @@ public void testCustomNumberEditorWithAllowEmpty() { bw.setPropertyValue("long1", "5"); bw.setPropertyValue("long2", "6"); - assertThat(new Long("5").equals(bw.getPropertyValue("long1"))).as("Correct long1 value").isTrue(); + assertThat(Long.valueOf("5").equals(bw.getPropertyValue("long1"))).as("Correct long1 value").isTrue(); assertThat(tb.getLong1() == 5).as("Correct long1 value").isTrue(); - assertThat(new Long("6").equals(bw.getPropertyValue("long2"))).as("Correct long2 value").isTrue(); - assertThat(new Long("6").equals(tb.getLong2())).as("Correct long2 value").isTrue(); + assertThat(Long.valueOf("6").equals(bw.getPropertyValue("long2"))).as("Correct long2 value").isTrue(); + assertThat(Long.valueOf("6").equals(tb.getLong2())).as("Correct long2 value").isTrue(); bw.setPropertyValue("long2", ""); assertThat(bw.getPropertyValue("long2") == null).as("Correct long2 value").isTrue(); @@ -458,7 +458,7 @@ public void testCustomNumberEditorWithAllowEmpty() { } @Test - public void testCustomNumberEditorWithFrenchBigDecimal() throws Exception { + void testCustomNumberEditorWithFrenchBigDecimal() throws Exception { NumberFormat nf = NumberFormat.getNumberInstance(Locale.FRENCH); NumberTestBean tb = new NumberTestBean(); BeanWrapper bw = new BeanWrapperImpl(tb); @@ -475,14 +475,14 @@ public void testCustomNumberEditorWithFrenchBigDecimal() throws Exception { } @Test - public void testParseShortGreaterThanMaxValueWithoutNumberFormat() { + void testParseShortGreaterThanMaxValueWithoutNumberFormat() { CustomNumberEditor editor = new CustomNumberEditor(Short.class, true); assertThatExceptionOfType(NumberFormatException.class).as("greater than Short.MAX_VALUE + 1").isThrownBy(() -> editor.setAsText(String.valueOf(Short.MAX_VALUE + 1))); } @Test - public void testByteArrayPropertyEditor() { + void testByteArrayPropertyEditor() { PrimitiveArrayBean bean = new PrimitiveArrayBean(); BeanWrapper bw = new BeanWrapperImpl(bean); bw.setPropertyValue("byteArray", "myvalue"); @@ -490,7 +490,7 @@ public void testByteArrayPropertyEditor() { } @Test - public void testCharArrayPropertyEditor() { + void testCharArrayPropertyEditor() { PrimitiveArrayBean bean = new PrimitiveArrayBean(); BeanWrapper bw = new BeanWrapperImpl(bean); bw.setPropertyValue("charArray", "myvalue"); @@ -498,7 +498,7 @@ public void testCharArrayPropertyEditor() { } @Test - public void testCharacterEditor() { + void testCharacterEditor() { CharBean cb = new CharBean(); BeanWrapper bw = new BeanWrapperImpl(cb); @@ -520,78 +520,78 @@ public void testCharacterEditor() { } @Test - public void testCharacterEditorWithAllowEmpty() { + void testCharacterEditorWithAllowEmpty() { CharBean cb = new CharBean(); BeanWrapper bw = new BeanWrapperImpl(cb); bw.registerCustomEditor(Character.class, new CharacterEditor(true)); - bw.setPropertyValue("myCharacter", new Character('c')); - assertThat(cb.getMyCharacter()).isEqualTo(new Character('c')); + bw.setPropertyValue("myCharacter", 'c'); + assertThat(cb.getMyCharacter()).isEqualTo(Character.valueOf('c')); bw.setPropertyValue("myCharacter", "c"); - assertThat(cb.getMyCharacter()).isEqualTo(new Character('c')); + assertThat(cb.getMyCharacter()).isEqualTo(Character.valueOf('c')); bw.setPropertyValue("myCharacter", "\u0041"); - assertThat(cb.getMyCharacter()).isEqualTo(new Character('A')); + assertThat(cb.getMyCharacter()).isEqualTo(Character.valueOf('A')); bw.setPropertyValue("myCharacter", " "); - assertThat(cb.getMyCharacter()).isEqualTo(new Character(' ')); + assertThat(cb.getMyCharacter()).isEqualTo(Character.valueOf(' ')); bw.setPropertyValue("myCharacter", ""); assertThat(cb.getMyCharacter()).isNull(); } @Test - public void testCharacterEditorSetAsTextWithStringLongerThanOneCharacter() throws Exception { + void testCharacterEditorSetAsTextWithStringLongerThanOneCharacter() throws Exception { PropertyEditor charEditor = new CharacterEditor(false); assertThatIllegalArgumentException().isThrownBy(() -> charEditor.setAsText("ColdWaterCanyon")); } @Test - public void testCharacterEditorGetAsTextReturnsEmptyStringIfValueIsNull() throws Exception { + void testCharacterEditorGetAsTextReturnsEmptyStringIfValueIsNull() throws Exception { PropertyEditor charEditor = new CharacterEditor(false); - assertThat(charEditor.getAsText()).isEqualTo(""); + assertThat(charEditor.getAsText()).isEmpty(); charEditor = new CharacterEditor(true); charEditor.setAsText(null); - assertThat(charEditor.getAsText()).isEqualTo(""); + assertThat(charEditor.getAsText()).isEmpty(); charEditor.setAsText(""); - assertThat(charEditor.getAsText()).isEqualTo(""); + assertThat(charEditor.getAsText()).isEmpty(); charEditor.setAsText(" "); assertThat(charEditor.getAsText()).isEqualTo(" "); } @Test - public void testCharacterEditorSetAsTextWithNullNotAllowingEmptyAsNull() throws Exception { + void testCharacterEditorSetAsTextWithNullNotAllowingEmptyAsNull() throws Exception { PropertyEditor charEditor = new CharacterEditor(false); assertThatIllegalArgumentException().isThrownBy(() -> charEditor.setAsText(null)); } @Test - public void testClassEditor() { + void testClassEditor() { PropertyEditor classEditor = new ClassEditor(); classEditor.setAsText(TestBean.class.getName()); assertThat(classEditor.getValue()).isEqualTo(TestBean.class); assertThat(classEditor.getAsText()).isEqualTo(TestBean.class.getName()); classEditor.setAsText(null); - assertThat(classEditor.getAsText()).isEqualTo(""); + assertThat(classEditor.getAsText()).isEmpty(); classEditor.setAsText(""); - assertThat(classEditor.getAsText()).isEqualTo(""); + assertThat(classEditor.getAsText()).isEmpty(); classEditor.setAsText("\t "); - assertThat(classEditor.getAsText()).isEqualTo(""); + assertThat(classEditor.getAsText()).isEmpty(); } @Test - public void testClassEditorWithNonExistentClass() throws Exception { + void testClassEditorWithNonExistentClass() throws Exception { PropertyEditor classEditor = new ClassEditor(); assertThatIllegalArgumentException().isThrownBy(() -> classEditor.setAsText("hairdresser.on.Fire")); } @Test - public void testClassEditorWithArray() { + void testClassEditorWithArray() { PropertyEditor classEditor = new ClassEditor(); classEditor.setAsText("org.springframework.beans.testfixture.beans.TestBean[]"); assertThat(classEditor.getValue()).isEqualTo(TestBean[].class); @@ -602,7 +602,7 @@ public void testClassEditorWithArray() { * SPR_2165 - ClassEditor is inconsistent with multidimensional arrays */ @Test - public void testGetAsTextWithTwoDimensionalArray() throws Exception { + void testGetAsTextWithTwoDimensionalArray() throws Exception { String[][] chessboard = new String[8][8]; ClassEditor editor = new ClassEditor(); editor.setValue(chessboard.getClass()); @@ -613,7 +613,7 @@ public void testGetAsTextWithTwoDimensionalArray() throws Exception { * SPR_2165 - ClassEditor is inconsistent with multidimensional arrays */ @Test - public void testGetAsTextWithRidiculousMultiDimensionalArray() throws Exception { + void testGetAsTextWithRidiculousMultiDimensionalArray() throws Exception { String[][][][][] ridiculousChessboard = new String[8][4][0][1][3]; ClassEditor editor = new ClassEditor(); editor.setValue(ridiculousChessboard.getClass()); @@ -621,7 +621,7 @@ public void testGetAsTextWithRidiculousMultiDimensionalArray() throws Exception } @Test - public void testFileEditor() { + void testFileEditor() { PropertyEditor fileEditor = new FileEditor(); fileEditor.setAsText("file:myfile.txt"); assertThat(fileEditor.getValue()).isEqualTo(new File("myfile.txt")); @@ -629,7 +629,7 @@ public void testFileEditor() { } @Test - public void testFileEditorWithRelativePath() { + void testFileEditorWithRelativePath() { PropertyEditor fileEditor = new FileEditor(); try { fileEditor.setAsText("myfile.txt"); @@ -641,7 +641,7 @@ public void testFileEditorWithRelativePath() { } @Test - public void testFileEditorWithAbsolutePath() { + void testFileEditorWithAbsolutePath() { PropertyEditor fileEditor = new FileEditor(); // testing on Windows if (new File("C:/myfile.txt").isAbsolute()) { @@ -656,18 +656,18 @@ public void testFileEditorWithAbsolutePath() { } @Test - public void testLocaleEditor() { + void testLocaleEditor() { PropertyEditor localeEditor = new LocaleEditor(); localeEditor.setAsText("en_CA"); assertThat(localeEditor.getValue()).isEqualTo(Locale.CANADA); assertThat(localeEditor.getAsText()).isEqualTo("en_CA"); localeEditor = new LocaleEditor(); - assertThat(localeEditor.getAsText()).isEqualTo(""); + assertThat(localeEditor.getAsText()).isEmpty(); } @Test - public void testPatternEditor() { + void testPatternEditor() { final String REGEX = "a.*"; PropertyEditor patternEditor = new PatternEditor(); @@ -676,15 +676,15 @@ public void testPatternEditor() { assertThat(patternEditor.getAsText()).isEqualTo(REGEX); patternEditor = new PatternEditor(); - assertThat(patternEditor.getAsText()).isEqualTo(""); + assertThat(patternEditor.getAsText()).isEmpty(); patternEditor = new PatternEditor(); patternEditor.setAsText(null); - assertThat(patternEditor.getAsText()).isEqualTo(""); + assertThat(patternEditor.getAsText()).isEmpty(); } @Test - public void testCustomBooleanEditor() { + void testCustomBooleanEditor() { CustomBooleanEditor editor = new CustomBooleanEditor(false); editor.setAsText("true"); @@ -696,15 +696,15 @@ public void testCustomBooleanEditor() { assertThat(editor.getAsText()).isEqualTo("false"); editor.setValue(null); - assertThat(editor.getValue()).isEqualTo(null); - assertThat(editor.getAsText()).isEqualTo(""); + assertThat(editor.getValue()).isNull(); + assertThat(editor.getAsText()).isEmpty(); assertThatIllegalArgumentException().isThrownBy(() -> editor.setAsText(null)); } @Test - public void testCustomBooleanEditorWithEmptyAsNull() { + void testCustomBooleanEditorWithEmptyAsNull() { CustomBooleanEditor editor = new CustomBooleanEditor(true); editor.setAsText("true"); @@ -716,34 +716,34 @@ public void testCustomBooleanEditorWithEmptyAsNull() { assertThat(editor.getAsText()).isEqualTo("false"); editor.setValue(null); - assertThat(editor.getValue()).isEqualTo(null); - assertThat(editor.getAsText()).isEqualTo(""); + assertThat(editor.getValue()).isNull(); + assertThat(editor.getAsText()).isEmpty(); } @Test - public void testCustomDateEditor() { + void testCustomDateEditor() { CustomDateEditor editor = new CustomDateEditor(null, false); editor.setValue(null); - assertThat(editor.getValue()).isEqualTo(null); - assertThat(editor.getAsText()).isEqualTo(""); + assertThat(editor.getValue()).isNull(); + assertThat(editor.getAsText()).isEmpty(); } @Test - public void testCustomDateEditorWithEmptyAsNull() { + void testCustomDateEditorWithEmptyAsNull() { CustomDateEditor editor = new CustomDateEditor(null, true); editor.setValue(null); - assertThat(editor.getValue()).isEqualTo(null); - assertThat(editor.getAsText()).isEqualTo(""); + assertThat(editor.getValue()).isNull(); + assertThat(editor.getAsText()).isEmpty(); } @Test - public void testCustomDateEditorWithExactDateLength() { + void testCustomDateEditorWithExactDateLength() { int maxLength = 10; String validDate = "01/01/2005"; String invalidDate = "01/01/05"; - assertThat(validDate.length() == maxLength).isTrue(); - assertThat(invalidDate.length() == maxLength).isFalse(); + assertThat(validDate).hasSize(maxLength); + assertThat(invalidDate.length()).isNotEqualTo(maxLength); CustomDateEditor editor = new CustomDateEditor(new SimpleDateFormat("MM/dd/yyyy"), true, maxLength); editor.setAsText(validDate); @@ -753,39 +753,39 @@ public void testCustomDateEditorWithExactDateLength() { } @Test - public void testCustomNumberEditor() { + void testCustomNumberEditor() { CustomNumberEditor editor = new CustomNumberEditor(Integer.class, false); editor.setAsText("5"); assertThat(editor.getValue()).isEqualTo(5); assertThat(editor.getAsText()).isEqualTo("5"); editor.setValue(null); - assertThat(editor.getValue()).isEqualTo(null); - assertThat(editor.getAsText()).isEqualTo(""); + assertThat(editor.getValue()).isNull(); + assertThat(editor.getAsText()).isEmpty(); } @Test - public void testCustomNumberEditorWithHex() { + void testCustomNumberEditorWithHex() { CustomNumberEditor editor = new CustomNumberEditor(Integer.class, false); editor.setAsText("0x" + Integer.toHexString(64)); assertThat(editor.getValue()).isEqualTo(64); } @Test - public void testCustomNumberEditorWithEmptyAsNull() { + void testCustomNumberEditorWithEmptyAsNull() { CustomNumberEditor editor = new CustomNumberEditor(Integer.class, true); editor.setAsText("5"); assertThat(editor.getValue()).isEqualTo(5); assertThat(editor.getAsText()).isEqualTo("5"); editor.setAsText(""); - assertThat(editor.getValue()).isEqualTo(null); - assertThat(editor.getAsText()).isEqualTo(""); + assertThat(editor.getValue()).isNull(); + assertThat(editor.getAsText()).isEmpty(); editor.setValue(null); - assertThat(editor.getValue()).isEqualTo(null); - assertThat(editor.getAsText()).isEqualTo(""); + assertThat(editor.getValue()).isNull(); + assertThat(editor.getAsText()).isEmpty(); } @Test - public void testStringTrimmerEditor() { + void testStringTrimmerEditor() { StringTrimmerEditor editor = new StringTrimmerEditor(false); editor.setAsText("test"); assertThat(editor.getValue()).isEqualTo("test"); @@ -795,15 +795,15 @@ public void testStringTrimmerEditor() { assertThat(editor.getAsText()).isEqualTo("test"); editor.setAsText(""); assertThat(editor.getValue()).isEqualTo(""); - assertThat(editor.getAsText()).isEqualTo(""); + assertThat(editor.getAsText()).isEmpty(); editor.setValue(null); - assertThat(editor.getAsText()).isEqualTo(""); + assertThat(editor.getAsText()).isEmpty(); editor.setAsText(null); - assertThat(editor.getAsText()).isEqualTo(""); + assertThat(editor.getAsText()).isEmpty(); } @Test - public void testStringTrimmerEditorWithEmptyAsNull() { + void testStringTrimmerEditorWithEmptyAsNull() { StringTrimmerEditor editor = new StringTrimmerEditor(true); editor.setAsText("test"); assertThat(editor.getValue()).isEqualTo("test"); @@ -812,14 +812,14 @@ public void testStringTrimmerEditorWithEmptyAsNull() { assertThat(editor.getValue()).isEqualTo("test"); assertThat(editor.getAsText()).isEqualTo("test"); editor.setAsText(" "); - assertThat(editor.getValue()).isEqualTo(null); - assertThat(editor.getAsText()).isEqualTo(""); + assertThat(editor.getValue()).isNull(); + assertThat(editor.getAsText()).isEmpty(); editor.setValue(null); - assertThat(editor.getAsText()).isEqualTo(""); + assertThat(editor.getAsText()).isEmpty(); } @Test - public void testStringTrimmerEditorWithCharsToDelete() { + void testStringTrimmerEditorWithCharsToDelete() { StringTrimmerEditor editor = new StringTrimmerEditor("\r\n\f", false); editor.setAsText("te\ns\ft"); assertThat(editor.getValue()).isEqualTo("test"); @@ -829,13 +829,13 @@ public void testStringTrimmerEditorWithCharsToDelete() { assertThat(editor.getAsText()).isEqualTo("test"); editor.setAsText(""); assertThat(editor.getValue()).isEqualTo(""); - assertThat(editor.getAsText()).isEqualTo(""); + assertThat(editor.getAsText()).isEmpty(); editor.setValue(null); - assertThat(editor.getAsText()).isEqualTo(""); + assertThat(editor.getAsText()).isEmpty(); } @Test - public void testStringTrimmerEditorWithCharsToDeleteAndEmptyAsNull() { + void testStringTrimmerEditorWithCharsToDeleteAndEmptyAsNull() { StringTrimmerEditor editor = new StringTrimmerEditor("\r\n\f", true); editor.setAsText("te\ns\ft"); assertThat(editor.getValue()).isEqualTo("test"); @@ -844,14 +844,14 @@ public void testStringTrimmerEditorWithCharsToDeleteAndEmptyAsNull() { assertThat(editor.getValue()).isEqualTo("test"); assertThat(editor.getAsText()).isEqualTo("test"); editor.setAsText(" \n\f "); - assertThat(editor.getValue()).isEqualTo(null); - assertThat(editor.getAsText()).isEqualTo(""); + assertThat(editor.getValue()).isNull(); + assertThat(editor.getAsText()).isEmpty(); editor.setValue(null); - assertThat(editor.getAsText()).isEqualTo(""); + assertThat(editor.getAsText()).isEmpty(); } @Test - public void testIndexedPropertiesWithCustomEditorForType() { + void testIndexedPropertiesWithCustomEditorForType() { IndexedTestBean bean = new IndexedTestBean(); BeanWrapper bw = new BeanWrapperImpl(bean); bw.registerCustomEditor(String.class, new PropertyEditorSupport() { @@ -904,7 +904,7 @@ public void setAsText(String text) throws IllegalArgumentException { } @Test - public void testIndexedPropertiesWithCustomEditorForProperty() { + void testIndexedPropertiesWithCustomEditorForProperty() { IndexedTestBean bean = new IndexedTestBean(false); BeanWrapper bw = new BeanWrapperImpl(bean); bw.registerCustomEditor(String.class, "array.name", new PropertyEditorSupport() { @@ -971,7 +971,7 @@ public void setAsText(String text) throws IllegalArgumentException { } @Test - public void testIndexedPropertiesWithIndividualCustomEditorForProperty() { + void testIndexedPropertiesWithIndividualCustomEditorForProperty() { IndexedTestBean bean = new IndexedTestBean(false); BeanWrapper bw = new BeanWrapperImpl(bean); bw.registerCustomEditor(String.class, "array[0].name", new PropertyEditorSupport() { @@ -1056,7 +1056,7 @@ public void setAsText(String text) throws IllegalArgumentException { } @Test - public void testNestedIndexedPropertiesWithCustomEditorForProperty() { + void testNestedIndexedPropertiesWithCustomEditorForProperty() { IndexedTestBean bean = new IndexedTestBean(); TestBean tb0 = bean.getArray()[0]; TestBean tb1 = bean.getArray()[1]; @@ -1140,7 +1140,7 @@ public String getAsText() { } @Test - public void testNestedIndexedPropertiesWithIndexedCustomEditorForProperty() { + void testNestedIndexedPropertiesWithIndexedCustomEditorForProperty() { IndexedTestBean bean = new IndexedTestBean(); TestBean tb0 = bean.getArray()[0]; TestBean tb1 = bean.getArray()[1]; @@ -1191,7 +1191,7 @@ public void setAsText(String text) throws IllegalArgumentException { } @Test - public void testIndexedPropertiesWithDirectAccessAndPropertyEditors() { + void testIndexedPropertiesWithDirectAccessAndPropertyEditors() { IndexedTestBean bean = new IndexedTestBean(); BeanWrapper bw = new BeanWrapperImpl(bean); bw.registerCustomEditor(TestBean.class, "array", new PropertyEditorSupport() { @@ -1245,7 +1245,7 @@ public String getAsText() { } @Test - public void testIndexedPropertiesWithDirectAccessAndSpecificPropertyEditors() { + void testIndexedPropertiesWithDirectAccessAndSpecificPropertyEditors() { IndexedTestBean bean = new IndexedTestBean(); BeanWrapper bw = new BeanWrapperImpl(bean); bw.registerCustomEditor(TestBean.class, "array[0]", new PropertyEditorSupport() { @@ -1332,7 +1332,7 @@ public String getAsText() { } @Test - public void testIndexedPropertiesWithListPropertyEditor() { + void testIndexedPropertiesWithListPropertyEditor() { IndexedTestBean bean = new IndexedTestBean(); BeanWrapper bw = new BeanWrapperImpl(bean); bw.registerCustomEditor(List.class, "list", new PropertyEditorSupport() { @@ -1350,7 +1350,7 @@ public void setAsText(String text) throws IllegalArgumentException { } @Test - public void testConversionToOldCollections() throws PropertyVetoException { + void testConversionToOldCollections() throws PropertyVetoException { OldCollectionsBean tb = new OldCollectionsBean(); BeanWrapper bw = new BeanWrapperImpl(tb); bw.registerCustomEditor(Vector.class, new CustomCollectionEditor(Vector.class)); @@ -1367,7 +1367,7 @@ public void testConversionToOldCollections() throws PropertyVetoException { } @Test - public void testUninitializedArrayPropertyWithCustomEditor() { + void testUninitializedArrayPropertyWithCustomEditor() { IndexedTestBean bean = new IndexedTestBean(false); BeanWrapper bw = new BeanWrapperImpl(bean); PropertyEditor pe = new CustomNumberEditor(Integer.class, true); @@ -1383,7 +1383,7 @@ public void testUninitializedArrayPropertyWithCustomEditor() { } @Test - public void testArrayToArrayConversion() throws PropertyVetoException { + void testArrayToArrayConversion() throws PropertyVetoException { IndexedTestBean tb = new IndexedTestBean(); BeanWrapper bw = new BeanWrapperImpl(tb); bw.registerCustomEditor(TestBean.class, new PropertyEditorSupport() { @@ -1399,7 +1399,7 @@ public void setAsText(String text) throws IllegalArgumentException { } @Test - public void testArrayToStringConversion() throws PropertyVetoException { + void testArrayToStringConversion() throws PropertyVetoException { TestBean tb = new TestBean(); BeanWrapper bw = new BeanWrapperImpl(tb); bw.registerCustomEditor(String.class, new PropertyEditorSupport() { @@ -1408,16 +1408,16 @@ public void setAsText(String text) throws IllegalArgumentException { setValue("-" + text + "-"); } }); - bw.setPropertyValue("name", new String[] {"a", "b"}); + bw.setPropertyValue("name", new String[]{"a", "b"}); assertThat(tb.getName()).isEqualTo("-a,b-"); } @Test - public void testClassArrayEditorSunnyDay() throws Exception { + void testClassArrayEditorSunnyDay() throws Exception { ClassArrayEditor classArrayEditor = new ClassArrayEditor(); classArrayEditor.setAsText("java.lang.String,java.util.HashMap"); Class[] classes = (Class[]) classArrayEditor.getValue(); - assertThat(classes.length).isEqualTo(2); + assertThat(classes).hasSize(2); assertThat(classes[0]).isEqualTo(String.class); assertThat(classes[1]).isEqualTo(HashMap.class); assertThat(classArrayEditor.getAsText()).isEqualTo("java.lang.String,java.util.HashMap"); @@ -1426,11 +1426,11 @@ public void testClassArrayEditorSunnyDay() throws Exception { } @Test - public void testClassArrayEditorSunnyDayWithArrayTypes() throws Exception { + void testClassArrayEditorSunnyDayWithArrayTypes() throws Exception { ClassArrayEditor classArrayEditor = new ClassArrayEditor(); classArrayEditor.setAsText("java.lang.String[],java.util.Map[],int[],float[][][]"); Class[] classes = (Class[]) classArrayEditor.getValue(); - assertThat(classes.length).isEqualTo(4); + assertThat(classes).hasSize(4); assertThat(classes[0]).isEqualTo(String[].class); assertThat(classes[1]).isEqualTo(Map[].class); assertThat(classes[2]).isEqualTo(int[].class); @@ -1441,31 +1441,31 @@ public void testClassArrayEditorSunnyDayWithArrayTypes() throws Exception { } @Test - public void testClassArrayEditorSetAsTextWithNull() throws Exception { + void testClassArrayEditorSetAsTextWithNull() throws Exception { ClassArrayEditor editor = new ClassArrayEditor(); editor.setAsText(null); assertThat(editor.getValue()).isNull(); - assertThat(editor.getAsText()).isEqualTo(""); + assertThat(editor.getAsText()).isEmpty(); } @Test - public void testClassArrayEditorSetAsTextWithEmptyString() throws Exception { + void testClassArrayEditorSetAsTextWithEmptyString() throws Exception { ClassArrayEditor editor = new ClassArrayEditor(); editor.setAsText(""); assertThat(editor.getValue()).isNull(); - assertThat(editor.getAsText()).isEqualTo(""); + assertThat(editor.getAsText()).isEmpty(); } @Test - public void testClassArrayEditorSetAsTextWithWhitespaceString() throws Exception { + void testClassArrayEditorSetAsTextWithWhitespaceString() throws Exception { ClassArrayEditor editor = new ClassArrayEditor(); editor.setAsText("\n"); assertThat(editor.getValue()).isNull(); - assertThat(editor.getAsText()).isEqualTo(""); + assertThat(editor.getAsText()).isEmpty(); } @Test - public void testCharsetEditor() throws Exception { + void testCharsetEditor() throws Exception { CharsetEditor editor = new CharsetEditor(); String name = "UTF-8"; editor.setAsText(name); diff --git a/spring-context-indexer/spring-context-indexer.gradle b/spring-context-indexer/spring-context-indexer.gradle index a9769ada026a..2c1df2e91dc3 100644 --- a/spring-context-indexer/spring-context-indexer.gradle +++ b/spring-context-indexer/spring-context-indexer.gradle @@ -1,9 +1,9 @@ description = "Spring Context Indexer" dependencies { - testCompile(project(":spring-context")) - testCompile("javax.inject:javax.inject") - testCompile("javax.annotation:javax.annotation-api") - testCompile("javax.transaction:javax.transaction-api") - testCompile("org.eclipse.persistence:javax.persistence") + testImplementation(project(":spring-context")) + testImplementation("javax.inject:javax.inject") + testImplementation("javax.annotation:javax.annotation-api") + testImplementation("javax.transaction:javax.transaction-api") + testImplementation("org.eclipse.persistence:javax.persistence") } diff --git a/spring-context-support/spring-context-support.gradle b/spring-context-support/spring-context-support.gradle index f8a8631293ad..843d1920ebe4 100644 --- a/spring-context-support/spring-context-support.gradle +++ b/spring-context-support/spring-context-support.gradle @@ -1,9 +1,9 @@ description = "Spring Context Support" dependencies { - compile(project(":spring-beans")) - compile(project(":spring-context")) - compile(project(":spring-core")) + api(project(":spring-beans")) + api(project(":spring-context")) + api(project(":spring-core")) optional(project(":spring-jdbc")) // for Quartz support optional(project(":spring-tx")) // for Quartz support optional("javax.activation:javax.activation-api") @@ -14,18 +14,18 @@ dependencies { optional("org.quartz-scheduler:quartz") optional("org.codehaus.fabric3.api:commonj") optional("org.freemarker:freemarker") - testCompile(project(":spring-context")) - testCompile(testFixtures(project(":spring-beans"))) - testCompile(testFixtures(project(":spring-context"))) - testCompile(testFixtures(project(":spring-core"))) - testCompile(testFixtures(project(":spring-tx"))) - testCompile("org.hsqldb:hsqldb") - testCompile("org.hibernate:hibernate-validator") - testCompile("javax.annotation:javax.annotation-api") - testRuntime("org.ehcache:jcache") - testRuntime("org.ehcache:ehcache") - testRuntime("org.glassfish:javax.el") - testRuntime("com.sun.mail:javax.mail") + testImplementation(project(":spring-context")) + testImplementation(testFixtures(project(":spring-beans"))) + testImplementation(testFixtures(project(":spring-context"))) + testImplementation(testFixtures(project(":spring-core"))) + testImplementation(testFixtures(project(":spring-tx"))) + testImplementation("org.hsqldb:hsqldb") + testImplementation("org.hibernate:hibernate-validator") + testImplementation("javax.annotation:javax.annotation-api") + testRuntimeOnly("org.ehcache:jcache") + testRuntimeOnly("org.ehcache:ehcache") + testRuntimeOnly("org.glassfish:javax.el") + testRuntimeOnly("com.sun.mail:javax.mail") testFixturesApi("org.junit.jupiter:junit-jupiter-api") testFixturesImplementation("org.assertj:assertj-core") testFixturesImplementation("org.mockito:mockito-core") diff --git a/spring-context/spring-context.gradle b/spring-context/spring-context.gradle index 0b06a7c56f0f..221e0f12fe1a 100644 --- a/spring-context/spring-context.gradle +++ b/spring-context/spring-context.gradle @@ -4,10 +4,10 @@ apply plugin: "groovy" apply plugin: "kotlin" dependencies { - compile(project(":spring-aop")) - compile(project(":spring-beans")) - compile(project(":spring-core")) - compile(project(":spring-expression")) + api(project(":spring-aop")) + api(project(":spring-beans")) + api(project(":spring-core")) + api(project(":spring-expression")) optional(project(":spring-instrument")) optional("javax.annotation:javax.annotation-api") optional("javax.ejb:javax.ejb-api") @@ -26,22 +26,22 @@ dependencies { optional("org.jetbrains.kotlin:kotlin-reflect") optional("org.jetbrains.kotlin:kotlin-stdlib") optional("org.reactivestreams:reactive-streams") - testCompile(testFixtures(project(":spring-aop"))) - testCompile(testFixtures(project(":spring-beans"))) - testCompile(testFixtures(project(":spring-core"))) - testCompile("io.projectreactor:reactor-core") - testCompile("org.codehaus.groovy:groovy-jsr223") - testCompile("org.codehaus.groovy:groovy-test") - testCompile("org.codehaus.groovy:groovy-xml") - testCompile("org.apache.commons:commons-pool2") - testCompile("javax.inject:javax.inject-tck") - testCompile("org.awaitility:awaitility") - testRuntime("javax.xml.bind:jaxb-api") - testRuntime("org.glassfish:javax.el") + testImplementation(testFixtures(project(":spring-aop"))) + testImplementation(testFixtures(project(":spring-beans"))) + testImplementation(testFixtures(project(":spring-core"))) + testImplementation("io.projectreactor:reactor-core") + testImplementation("org.codehaus.groovy:groovy-jsr223") + testImplementation("org.codehaus.groovy:groovy-test") + testImplementation("org.codehaus.groovy:groovy-xml") + testImplementation("org.apache.commons:commons-pool2") + testImplementation("javax.inject:javax.inject-tck") + testImplementation("org.awaitility:awaitility") + testRuntimeOnly("javax.xml.bind:jaxb-api") + testRuntimeOnly("org.glassfish:javax.el") // Substitute for javax.management:jmxremote_optional:1.0.1_04 (not available on Maven Central) - testRuntime("org.glassfish.external:opendmk_jmxremote_optional_jar") - testRuntime("org.javamoney:moneta") - testRuntime("org.junit.vintage:junit-vintage-engine") // for @Inject TCK + testRuntimeOnly("org.glassfish.external:opendmk_jmxremote_optional_jar") + testRuntimeOnly("org.javamoney:moneta") + testRuntimeOnly("org.junit.vintage:junit-vintage-engine") // for @Inject TCK testFixturesApi("org.junit.jupiter:junit-jupiter-api") testFixturesImplementation(testFixtures(project(":spring-beans"))) testFixturesImplementation("com.google.code.findbugs:jsr305") diff --git a/spring-context/src/main/java/org/springframework/cache/annotation/Cacheable.java b/spring-context/src/main/java/org/springframework/cache/annotation/Cacheable.java index b93cf9373f8b..e1d2700a4c4c 100644 --- a/spring-context/src/main/java/org/springframework/cache/annotation/Cacheable.java +++ b/spring-context/src/main/java/org/springframework/cache/annotation/Cacheable.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2021 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. @@ -38,9 +38,11 @@ * replace the default one (see {@link #keyGenerator}). * *

If no value is found in the cache for the computed key, the target method - * will be invoked and the returned value stored in the associated cache. Note - * that Java8's {@code Optional} return types are automatically handled and its - * content is stored in the cache if present. + * will be invoked and the returned value will be stored in the associated cache. + * Note that {@link java.util.Optional} return types are unwrapped automatically. + * If an {@code Optional} value is {@linkplain java.util.Optional#isPresent() + * present}, it will be stored in the associated cache. If an {@code Optional} + * value is not present, {@code null} will be stored in the associated cache. * *

This annotation may be used as a meta-annotation to create custom * composed annotations with attribute overrides. diff --git a/spring-context/src/main/java/org/springframework/scheduling/annotation/EnableScheduling.java b/spring-context/src/main/java/org/springframework/scheduling/annotation/EnableScheduling.java index d94b5f5e9c79..e35b0a799291 100644 --- a/spring-context/src/main/java/org/springframework/scheduling/annotation/EnableScheduling.java +++ b/spring-context/src/main/java/org/springframework/scheduling/annotation/EnableScheduling.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2021 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. @@ -31,7 +31,7 @@ /** * Enables Spring's scheduled task execution capability, similar to * functionality found in Spring's {@code } XML namespace. To be used - * on @{@link Configuration} classes as follows: + * on {@link Configuration @Configuration} classes as follows: * *

  * @Configuration
@@ -41,8 +41,8 @@
  *     // various @Bean definitions
  * }
* - * This enables detection of @{@link Scheduled} annotations on any Spring-managed - * bean in the container. For example, given a class {@code MyTask} + *

This enables detection of {@link Scheduled @Scheduled} annotations on any + * Spring-managed bean in the container. For example, given a class {@code MyTask}: * *

  * package com.myco.tasks;
@@ -55,7 +55,7 @@
  *     }
  * }
* - * the following configuration would ensure that {@code MyTask.work()} is called + *

the following configuration would ensure that {@code MyTask.work()} is called * once every 1000 ms: * *

@@ -69,7 +69,7 @@
  *     }
  * }
* - * Alternatively, if {@code MyTask} were annotated with {@code @Component}, the + *

Alternatively, if {@code MyTask} were annotated with {@code @Component}, the * following configuration would ensure that its {@code @Scheduled} method is * invoked at the desired interval: * @@ -80,7 +80,7 @@ * public class AppConfig { * } * - * Methods annotated with {@code @Scheduled} may even be declared directly within + *

Methods annotated with {@code @Scheduled} may even be declared directly within * {@code @Configuration} classes: * *

@@ -94,7 +94,7 @@
  *     }
  * }
* - *

By default, will be searching for an associated scheduler definition: either + *

By default, Spring will search for an associated scheduler definition: either * a unique {@link org.springframework.scheduling.TaskScheduler} bean in the context, * or a {@code TaskScheduler} bean named "taskScheduler" otherwise; the same lookup * will also be performed for a {@link java.util.concurrent.ScheduledExecutorService} @@ -141,11 +141,7 @@ * public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { * taskRegistrar.setScheduler(taskScheduler()); * taskRegistrar.addTriggerTask( - * new Runnable() { - * public void run() { - * myTask().work(); - * } - * }, + * () -> myTask().work(), * new CustomTrigger() * ); * } @@ -165,7 +161,7 @@ * configuration: * *

- * <beans>
+ * <beans>
  *
  *     <task:annotation-driven scheduler="taskScheduler"/>
  *
@@ -180,13 +176,13 @@
  * </beans>
  * 
* - * The examples are equivalent save that in XML a fixed-rate period is used + *

The examples are equivalent save that in XML a fixed-rate period is used * instead of a custom {@code Trigger} implementation; this is because the * {@code task:} namespace {@code scheduled} cannot easily expose such support. This is * but one demonstration how the code-based approach allows for maximum configurability - * through direct access to actual componentry.

+ * through direct access to actual componentry. * - * Note: {@code @EnableScheduling} applies to its local application context only, + *

Note: {@code @EnableScheduling} applies to its local application context only, * allowing for selective scheduling of beans at different levels. Please redeclare * {@code @EnableScheduling} in each individual context, e.g. the common root web * application context and any separate {@code DispatcherServlet} application contexts, diff --git a/spring-context/src/main/java/org/springframework/scheduling/annotation/Scheduled.java b/spring-context/src/main/java/org/springframework/scheduling/annotation/Scheduled.java index 415c72381792..f3aa81296a23 100644 --- a/spring-context/src/main/java/org/springframework/scheduling/annotation/Scheduled.java +++ b/spring-context/src/main/java/org/springframework/scheduling/annotation/Scheduled.java @@ -22,6 +22,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.util.concurrent.TimeUnit; import org.springframework.scheduling.config.ScheduledTaskRegistrar; @@ -37,7 +38,7 @@ *

Processing of {@code @Scheduled} annotations is performed by * registering a {@link ScheduledAnnotationBeanPostProcessor}. This can be * done manually or, more conveniently, through the {@code } - * element or @{@link EnableScheduling} annotation. + * XML element or {@link EnableScheduling @EnableScheduling} annotation. * *

This annotation may be used as a meta-annotation to create custom * composed annotations with attribute overrides. @@ -46,6 +47,8 @@ * @author Juergen Hoeller * @author Dave Syer * @author Chris Beams + * @author Victor Brown + * @author Sam Brannen * @since 3.0 * @see EnableScheduling * @see ScheduledAnnotationBeanPostProcessor @@ -101,52 +104,75 @@ String zone() default ""; /** - * Execute the annotated method with a fixed period in milliseconds between the - * end of the last invocation and the start of the next. - * @return the delay in milliseconds + * Execute the annotated method with a fixed period between the end of the + * last invocation and the start of the next. + *

The time unit is milliseconds by default but can be overridden via + * {@link #timeUnit}. + * @return the delay */ long fixedDelay() default -1; /** - * Execute the annotated method with a fixed period in milliseconds between the - * end of the last invocation and the start of the next. - * @return the delay in milliseconds as a String value, e.g. a placeholder + * Execute the annotated method with a fixed period between the end of the + * last invocation and the start of the next. + *

The time unit is milliseconds by default but can be overridden via + * {@link #timeUnit}. + * @return the delay as a String value — for example, a placeholder * or a {@link java.time.Duration#parse java.time.Duration} compliant value * @since 3.2.2 */ String fixedDelayString() default ""; /** - * Execute the annotated method with a fixed period in milliseconds between - * invocations. - * @return the period in milliseconds + * Execute the annotated method with a fixed period between invocations. + *

The time unit is milliseconds by default but can be overridden via + * {@link #timeUnit}. + * @return the period */ long fixedRate() default -1; /** - * Execute the annotated method with a fixed period in milliseconds between - * invocations. - * @return the period in milliseconds as a String value, e.g. a placeholder + * Execute the annotated method with a fixed period between invocations. + *

The time unit is milliseconds by default but can be overridden via + * {@link #timeUnit}. + * @return the period as a String value — for example, a placeholder * or a {@link java.time.Duration#parse java.time.Duration} compliant value * @since 3.2.2 */ String fixedRateString() default ""; /** - * Number of milliseconds to delay before the first execution of a + * Number of units of time to delay before the first execution of a * {@link #fixedRate} or {@link #fixedDelay} task. - * @return the initial delay in milliseconds + *

The time unit is milliseconds by default but can be overridden via + * {@link #timeUnit}. + * @return the initial * @since 3.2 */ long initialDelay() default -1; /** - * Number of milliseconds to delay before the first execution of a + * Number of units of time to delay before the first execution of a * {@link #fixedRate} or {@link #fixedDelay} task. - * @return the initial delay in milliseconds as a String value, e.g. a placeholder + *

The time unit is milliseconds by default but can be overridden via + * {@link #timeUnit}. + * @return the initial delay as a String value — for example, a placeholder * or a {@link java.time.Duration#parse java.time.Duration} compliant value * @since 3.2.2 */ String initialDelayString() default ""; + /** + * The {@link TimeUnit} to use for {@link #fixedDelay}, {@link #fixedDelayString}, + * {@link #fixedRate}, {@link #fixedRateString}, {@link #initialDelay}, and + * {@link #initialDelayString}. + *

Defaults to {@link TimeUnit#MILLISECONDS}. + *

This attribute is ignored for {@linkplain #cron() cron expressions} + * and for {@link java.time.Duration} values supplied via {@link #fixedDelayString}, + * {@link #fixedRateString}, or {@link #initialDelayString}. + * @return the {@code TimeUnit} to use + * @since 5.3.10 + */ + TimeUnit timeUnit() default TimeUnit.MILLISECONDS; + } diff --git a/spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java b/spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java index 14b73d6d7f7c..f0aae203468a 100644 --- a/spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java +++ b/spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java @@ -30,6 +30,7 @@ import java.util.TimeZone; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -77,9 +78,10 @@ import org.springframework.util.StringValueResolver; /** - * Bean post-processor that registers methods annotated with @{@link Scheduled} - * to be invoked by a {@link org.springframework.scheduling.TaskScheduler} according - * to the "fixedRate", "fixedDelay", or "cron" expression provided via the annotation. + * Bean post-processor that registers methods annotated with + * {@link Scheduled @Scheduled} to be invoked by a + * {@link org.springframework.scheduling.TaskScheduler} according to the + * "fixedRate", "fixedDelay", or "cron" expression provided via the annotation. * *

This post-processor is automatically registered by Spring's * {@code } XML element, and also by the @@ -87,13 +89,16 @@ * *

Autodetects any {@link SchedulingConfigurer} instances in the container, * allowing for customization of the scheduler to be used or for fine-grained - * control over task registration (e.g. registration of {@link Trigger} tasks. - * See the @{@link EnableScheduling} javadocs for complete usage details. + * control over task registration (e.g. registration of {@link Trigger} tasks). + * See the {@link EnableScheduling @EnableScheduling} javadocs for complete usage + * details. * * @author Mark Fisher * @author Juergen Hoeller * @author Chris Beams * @author Elizabeth Chatman + * @author Victor Brown + * @author Sam Brannen * @since 3.0 * @see Scheduled * @see EnableScheduling @@ -150,7 +155,8 @@ public ScheduledAnnotationBeanPostProcessor() { /** * Create a {@code ScheduledAnnotationBeanPostProcessor} delegating to the * specified {@link ScheduledTaskRegistrar}. - * @param registrar the ScheduledTaskRegistrar to register @Scheduled tasks on + * @param registrar the ScheduledTaskRegistrar to register {@code @Scheduled} + * tasks on * @since 5.1 */ public ScheduledAnnotationBeanPostProcessor(ScheduledTaskRegistrar registrar) { @@ -383,7 +389,7 @@ public Object postProcessAfterInitialization(Object bean, String beanName) { /** * Process the given {@code @Scheduled} method declaration on the given bean. - * @param scheduled the @Scheduled annotation + * @param scheduled the {@code @Scheduled} annotation * @param method the method that the annotation has been declared on * @param bean the target bean instance * @see #createRunnable(Object, Method) @@ -398,7 +404,7 @@ protected void processScheduled(Scheduled scheduled, Method method, Object bean) Set tasks = new LinkedHashSet<>(4); // Determine initial delay - long initialDelay = scheduled.initialDelay(); + long initialDelay = convertToMillis(scheduled.initialDelay(), scheduled.timeUnit()); String initialDelayString = scheduled.initialDelayString(); if (StringUtils.hasText(initialDelayString)) { Assert.isTrue(initialDelay < 0, "Specify 'initialDelay' or 'initialDelayString', not both"); @@ -407,7 +413,7 @@ protected void processScheduled(Scheduled scheduled, Method method, Object bean) } if (StringUtils.hasLength(initialDelayString)) { try { - initialDelay = parseDelayAsLong(initialDelayString); + initialDelay = convertToMillis(initialDelayString, scheduled.timeUnit()); } catch (RuntimeException ex) { throw new IllegalArgumentException( @@ -446,12 +452,13 @@ protected void processScheduled(Scheduled scheduled, Method method, Object bean) } // Check fixed delay - long fixedDelay = scheduled.fixedDelay(); + long fixedDelay = convertToMillis(scheduled.fixedDelay(), scheduled.timeUnit()); if (fixedDelay >= 0) { Assert.isTrue(!processedSchedule, errorMessage); processedSchedule = true; tasks.add(this.registrar.scheduleFixedDelayTask(new FixedDelayTask(runnable, fixedDelay, initialDelay))); } + String fixedDelayString = scheduled.fixedDelayString(); if (StringUtils.hasText(fixedDelayString)) { if (this.embeddedValueResolver != null) { @@ -461,7 +468,7 @@ protected void processScheduled(Scheduled scheduled, Method method, Object bean) Assert.isTrue(!processedSchedule, errorMessage); processedSchedule = true; try { - fixedDelay = parseDelayAsLong(fixedDelayString); + fixedDelay = convertToMillis(fixedDelayString, scheduled.timeUnit()); } catch (RuntimeException ex) { throw new IllegalArgumentException( @@ -472,7 +479,7 @@ protected void processScheduled(Scheduled scheduled, Method method, Object bean) } // Check fixed rate - long fixedRate = scheduled.fixedRate(); + long fixedRate = convertToMillis(scheduled.fixedRate(), scheduled.timeUnit()); if (fixedRate >= 0) { Assert.isTrue(!processedSchedule, errorMessage); processedSchedule = true; @@ -487,7 +494,7 @@ protected void processScheduled(Scheduled scheduled, Method method, Object bean) Assert.isTrue(!processedSchedule, errorMessage); processedSchedule = true; try { - fixedRate = parseDelayAsLong(fixedRateString); + fixedRate = convertToMillis(fixedRateString, scheduled.timeUnit()); } catch (RuntimeException ex) { throw new IllegalArgumentException( @@ -527,11 +534,19 @@ protected Runnable createRunnable(Object target, Method method) { return new ScheduledMethodRunnable(target, invocableMethod); } - private static long parseDelayAsLong(String value) throws RuntimeException { - if (value.length() > 1 && (isP(value.charAt(0)) || isP(value.charAt(1)))) { + private static long convertToMillis(long value, TimeUnit timeUnit) { + return TimeUnit.MILLISECONDS.convert(value, timeUnit); + } + + private static long convertToMillis(String value, TimeUnit timeUnit) { + if (isDurationString(value)) { return Duration.parse(value).toMillis(); } - return Long.parseLong(value); + return convertToMillis(Long.parseLong(value), timeUnit); + } + + private static boolean isDurationString(String value) { + return (value.length() > 1 && (isP(value.charAt(0)) || isP(value.charAt(1)))); } private static boolean isP(char ch) { diff --git a/spring-context/src/main/java/org/springframework/scheduling/annotation/SchedulingConfigurer.java b/spring-context/src/main/java/org/springframework/scheduling/annotation/SchedulingConfigurer.java index 05283e3fd503..26f0076077f7 100644 --- a/spring-context/src/main/java/org/springframework/scheduling/annotation/SchedulingConfigurer.java +++ b/spring-context/src/main/java/org/springframework/scheduling/annotation/SchedulingConfigurer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2021 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. @@ -19,17 +19,17 @@ import org.springframework.scheduling.config.ScheduledTaskRegistrar; /** - * Optional interface to be implemented by @{@link - * org.springframework.context.annotation.Configuration Configuration} classes annotated - * with @{@link EnableScheduling}. Typically used for setting a specific + * Optional interface to be implemented by {@link + * org.springframework.context.annotation.Configuration @Configuration} classes annotated + * with {@link EnableScheduling @EnableScheduling}. Typically used for setting a specific * {@link org.springframework.scheduling.TaskScheduler TaskScheduler} bean to be used when * executing scheduled tasks or for registering scheduled tasks in a programmatic - * fashion as opposed to the declarative approach of using the @{@link Scheduled} - * annotation. For example, this may be necessary when implementing {@link - * org.springframework.scheduling.Trigger Trigger}-based tasks, which are not supported by - * the {@code @Scheduled} annotation. + * fashion as opposed to the declarative approach of using the + * {@link Scheduled @Scheduled} annotation. For example, this may be necessary + * when implementing {@link org.springframework.scheduling.Trigger Trigger}-based + * tasks, which are not supported by the {@code @Scheduled} annotation. * - *

See @{@link EnableScheduling} for detailed usage examples. + *

See {@link EnableScheduling @EnableScheduling} for detailed usage examples. * * @author Chris Beams * @since 3.1 diff --git a/spring-context/src/test/java/org/springframework/aop/aspectj/ProceedTests.java b/spring-context/src/test/java/org/springframework/aop/aspectj/ProceedTests.java index 895e40eee17c..da16e07c3660 100644 --- a/spring-context/src/test/java/org/springframework/aop/aspectj/ProceedTests.java +++ b/spring-context/src/test/java/org/springframework/aop/aspectj/ProceedTests.java @@ -162,13 +162,13 @@ public Object capitalize(ProceedingJoinPoint pjp, String value) throws Throwable public Object doubleOrQuits(ProceedingJoinPoint pjp) throws Throwable { int value = ((Integer) pjp.getArgs()[0]).intValue(); - pjp.getArgs()[0] = new Integer(value * 2); + pjp.getArgs()[0] = Integer.valueOf(value * 2); return pjp.proceed(); } public Object addOne(ProceedingJoinPoint pjp, Float value) throws Throwable { float fv = value.floatValue(); - return pjp.proceed(new Object[] {new Float(fv + 1.0F)}); + return pjp.proceed(new Object[] {Float.valueOf(fv + 1.0F)}); } public void captureStringArgument(JoinPoint tjp, String arg) { diff --git a/spring-context/src/test/java/org/springframework/aop/aspectj/autoproxy/AspectJAutoProxyCreatorTests.java b/spring-context/src/test/java/org/springframework/aop/aspectj/autoproxy/AspectJAutoProxyCreatorTests.java index 0b6d3394ffba..279e600ec9e8 100644 --- a/spring-context/src/test/java/org/springframework/aop/aspectj/autoproxy/AspectJAutoProxyCreatorTests.java +++ b/spring-context/src/test/java/org/springframework/aop/aspectj/autoproxy/AspectJAutoProxyCreatorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -20,8 +20,6 @@ import java.lang.annotation.RetentionPolicy; import java.lang.reflect.Method; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; @@ -40,7 +38,6 @@ import org.springframework.beans.PropertyValue; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.config.MethodInvokingFactoryBean; -import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.testfixture.beans.ITestBean; import org.springframework.beans.testfixture.beans.TestBean; @@ -66,9 +63,6 @@ */ public class AspectJAutoProxyCreatorTests { - private static final Log factoryLog = LogFactory.getLog(DefaultListableBeanFactory.class); - - @Test public void testAspectsAreApplied() { ClassPathXmlApplicationContext bf = newContext("aspects.xml"); diff --git a/spring-context/src/test/java/org/springframework/context/event/AnnotationDrivenEventListenerTests.java b/spring-context/src/test/java/org/springframework/context/event/AnnotationDrivenEventListenerTests.java index cd1e71a12d57..c493f075b1ae 100644 --- a/spring-context/src/test/java/org/springframework/context/event/AnnotationDrivenEventListenerTests.java +++ b/spring-context/src/test/java/org/springframework/context/event/AnnotationDrivenEventListenerTests.java @@ -79,7 +79,7 @@ * @author Stephane Nicoll * @author Juergen Hoeller */ -public class AnnotationDrivenEventListenerTests { +class AnnotationDrivenEventListenerTests { private ConfigurableApplicationContext context; @@ -97,7 +97,7 @@ public void closeContext() { @Test - public void simpleEventJavaConfig() { + void simpleEventJavaConfig() { load(TestEventListener.class); TestEvent event = new TestEvent(this, "test"); TestEventListener listener = this.context.getBean(TestEventListener.class); @@ -120,7 +120,7 @@ public void simpleEventJavaConfig() { } @Test - public void simpleEventXmlConfig() { + void simpleEventXmlConfig() { this.context = new ClassPathXmlApplicationContext( "org/springframework/context/event/simple-event-configuration.xml"); @@ -141,7 +141,7 @@ public void simpleEventXmlConfig() { } @Test - public void metaAnnotationIsDiscovered() { + void metaAnnotationIsDiscovered() { load(MetaAnnotationListenerTestBean.class); MetaAnnotationListenerTestBean bean = this.context.getBean(MetaAnnotationListenerTestBean.class); this.eventCollector.assertNoEventReceived(bean); @@ -159,7 +159,7 @@ public void metaAnnotationIsDiscovered() { } @Test - public void contextEventsAreReceived() { + void contextEventsAreReceived() { load(ContextEventListener.class); ContextEventListener listener = this.context.getBean(ContextEventListener.class); @@ -175,7 +175,7 @@ public void contextEventsAreReceived() { } @Test - public void methodSignatureNoEvent() { + void methodSignatureNoEvent() { @SuppressWarnings("resource") AnnotationConfigApplicationContext failingContext = new AnnotationConfigApplicationContext(); @@ -189,7 +189,7 @@ public void methodSignatureNoEvent() { } @Test - public void simpleReply() { + void simpleReply() { load(TestEventListener.class, ReplyEventListener.class); AnotherTestEvent event = new AnotherTestEvent(this, "dummy"); ReplyEventListener replyEventListener = this.context.getBean(ReplyEventListener.class); @@ -204,7 +204,7 @@ public void simpleReply() { } @Test - public void nullReplyIgnored() { + void nullReplyIgnored() { load(TestEventListener.class, ReplyEventListener.class); AnotherTestEvent event = new AnotherTestEvent(this, null); // No response ReplyEventListener replyEventListener = this.context.getBean(ReplyEventListener.class); @@ -219,7 +219,7 @@ public void nullReplyIgnored() { } @Test - public void arrayReply() { + void arrayReply() { load(TestEventListener.class, ReplyEventListener.class); AnotherTestEvent event = new AnotherTestEvent(this, new String[]{"first", "second"}); ReplyEventListener replyEventListener = this.context.getBean(ReplyEventListener.class); @@ -234,7 +234,7 @@ public void arrayReply() { } @Test - public void collectionReply() { + void collectionReply() { load(TestEventListener.class, ReplyEventListener.class); Set replies = new LinkedHashSet<>(); replies.add("first"); @@ -253,7 +253,7 @@ public void collectionReply() { } @Test - public void collectionReplyNullValue() { + void collectionReplyNullValue() { load(TestEventListener.class, ReplyEventListener.class); AnotherTestEvent event = new AnotherTestEvent(this, Arrays.asList(null, "test")); ReplyEventListener replyEventListener = this.context.getBean(ReplyEventListener.class); @@ -268,7 +268,7 @@ public void collectionReplyNullValue() { } @Test - public void listenableFutureReply() { + void listenableFutureReply() { load(TestEventListener.class, ReplyEventListener.class); SettableListenableFuture future = new SettableListenableFuture<>(); future.set("dummy"); @@ -285,7 +285,7 @@ public void listenableFutureReply() { } @Test - public void completableFutureReply() { + void completableFutureReply() { load(TestEventListener.class, ReplyEventListener.class); AnotherTestEvent event = new AnotherTestEvent(this, CompletableFuture.completedFuture("dummy")); ReplyEventListener replyEventListener = this.context.getBean(ReplyEventListener.class); @@ -300,7 +300,7 @@ public void completableFutureReply() { } @Test - public void monoReply() { + void monoReply() { load(TestEventListener.class, ReplyEventListener.class); AnotherTestEvent event = new AnotherTestEvent(this, Mono.just("dummy")); ReplyEventListener replyEventListener = this.context.getBean(ReplyEventListener.class); @@ -315,7 +315,7 @@ public void monoReply() { } @Test - public void fluxReply() { + void fluxReply() { load(TestEventListener.class, ReplyEventListener.class); AnotherTestEvent event = new AnotherTestEvent(this, Flux.just("dummy1", "dummy2")); ReplyEventListener replyEventListener = this.context.getBean(ReplyEventListener.class); @@ -330,7 +330,7 @@ public void fluxReply() { } @Test - public void eventListenerWorksWithSimpleInterfaceProxy() { + void eventListenerWorksWithSimpleInterfaceProxy() { load(ScopedProxyTestBean.class); SimpleService proxy = this.context.getBean(SimpleService.class); @@ -347,7 +347,7 @@ public void eventListenerWorksWithSimpleInterfaceProxy() { } @Test - public void eventListenerWorksWithAnnotatedInterfaceProxy() { + void eventListenerWorksWithAnnotatedInterfaceProxy() { load(AnnotatedProxyTestBean.class); AnnotatedSimpleService proxy = this.context.getBean(AnnotatedSimpleService.class); @@ -364,7 +364,7 @@ public void eventListenerWorksWithAnnotatedInterfaceProxy() { } @Test - public void eventListenerWorksWithCglibProxy() { + void eventListenerWorksWithCglibProxy() { load(CglibProxyTestBean.class); CglibProxyTestBean proxy = this.context.getBean(CglibProxyTestBean.class); @@ -381,14 +381,14 @@ public void eventListenerWorksWithCglibProxy() { } @Test - public void privateMethodOnCglibProxyFails() { + void privateMethodOnCglibProxyFails() { assertThatExceptionOfType(BeanInitializationException.class).isThrownBy(() -> load(CglibProxyWithPrivateMethod.class)) .withCauseInstanceOf(IllegalStateException.class); } @Test - public void eventListenerWorksWithCustomScope() { + void eventListenerWorksWithCustomScope() { load(CustomScopeTestBean.class); CustomScope customScope = new CustomScope(); this.context.getBeanFactory().registerScope("custom", customScope); @@ -417,7 +417,7 @@ public void eventListenerWorksWithCustomScope() { } @Test - public void asyncProcessingApplied() throws InterruptedException { + void asyncProcessingApplied() throws InterruptedException { loadAsync(AsyncEventListener.class); String threadName = Thread.currentThread().getName(); @@ -432,7 +432,7 @@ public void asyncProcessingApplied() throws InterruptedException { } @Test - public void asyncProcessingAppliedWithInterfaceProxy() throws InterruptedException { + void asyncProcessingAppliedWithInterfaceProxy() throws InterruptedException { doLoad(AsyncConfigurationWithInterfaces.class, SimpleProxyTestBean.class); String threadName = Thread.currentThread().getName(); @@ -447,7 +447,7 @@ public void asyncProcessingAppliedWithInterfaceProxy() throws InterruptedExcepti } @Test - public void asyncProcessingAppliedWithScopedProxy() throws InterruptedException { + void asyncProcessingAppliedWithScopedProxy() throws InterruptedException { doLoad(AsyncConfigurationWithInterfaces.class, ScopedProxyTestBean.class); String threadName = Thread.currentThread().getName(); @@ -462,7 +462,7 @@ public void asyncProcessingAppliedWithScopedProxy() throws InterruptedException } @Test - public void exceptionPropagated() { + void exceptionPropagated() { load(ExceptionEventListener.class); TestEvent event = new TestEvent(this, "fail"); ExceptionEventListener listener = this.context.getBean(ExceptionEventListener.class); @@ -475,7 +475,7 @@ public void exceptionPropagated() { } @Test - public void exceptionNotPropagatedWithAsync() throws InterruptedException { + void exceptionNotPropagatedWithAsync() throws InterruptedException { loadAsync(ExceptionEventListener.class); AnotherTestEvent event = new AnotherTestEvent(this, "fail"); ExceptionEventListener listener = this.context.getBean(ExceptionEventListener.class); @@ -489,7 +489,7 @@ public void exceptionNotPropagatedWithAsync() throws InterruptedException { } @Test - public void listenerWithSimplePayload() { + void listenerWithSimplePayload() { load(TestEventListener.class); TestEventListener listener = this.context.getBean(TestEventListener.class); @@ -500,7 +500,7 @@ public void listenerWithSimplePayload() { } @Test - public void listenerWithNonMatchingPayload() { + void listenerWithNonMatchingPayload() { load(TestEventListener.class); TestEventListener listener = this.context.getBean(TestEventListener.class); @@ -511,7 +511,7 @@ public void listenerWithNonMatchingPayload() { } @Test - public void replyWithPayload() { + void replyWithPayload() { load(TestEventListener.class, ReplyEventListener.class); AnotherTestEvent event = new AnotherTestEvent(this, "String"); ReplyEventListener replyEventListener = this.context.getBean(ReplyEventListener.class); @@ -527,7 +527,7 @@ public void replyWithPayload() { } @Test - public void listenerWithGenericApplicationEvent() { + void listenerWithGenericApplicationEvent() { load(GenericEventListener.class); GenericEventListener listener = this.context.getBean(GenericEventListener.class); @@ -538,7 +538,7 @@ public void listenerWithGenericApplicationEvent() { } @Test - public void listenerWithResolvableTypeEvent() { + void listenerWithResolvableTypeEvent() { load(ResolvableTypeEventListener.class); ResolvableTypeEventListener listener = this.context.getBean(ResolvableTypeEventListener.class); @@ -550,7 +550,7 @@ public void listenerWithResolvableTypeEvent() { } @Test - public void listenerWithResolvableTypeEventWrongGeneric() { + void listenerWithResolvableTypeEventWrongGeneric() { load(ResolvableTypeEventListener.class); ResolvableTypeEventListener listener = this.context.getBean(ResolvableTypeEventListener.class); @@ -562,12 +562,12 @@ public void listenerWithResolvableTypeEventWrongGeneric() { } @Test - public void conditionMatch() { + void conditionMatch() { validateConditionMatch(ConditionalEventListener.class); } @Test - public void conditionMatchWithProxy() { + void conditionMatchWithProxy() { validateConditionMatch(ConditionalEventListener.class, MethodValidationPostProcessor.class); } @@ -600,7 +600,7 @@ private void validateConditionMatch(Class... classes) { } @Test - public void conditionDoesNotMatch() { + void conditionDoesNotMatch() { long maxLong = Long.MAX_VALUE; load(ConditionalEventListener.class); TestEvent event = new TestEvent(this, "KO"); @@ -625,7 +625,7 @@ public void conditionDoesNotMatch() { } @Test - public void orderedListeners() { + void orderedListeners() { load(OrderedTestListener.class); OrderedTestListener listener = this.context.getBean(OrderedTestListener.class); @@ -635,7 +635,7 @@ public void orderedListeners() { } @Test @Disabled // SPR-15122 - public void listenersReceiveEarlyEvents() { + void listenersReceiveEarlyEvents() { load(EventOnPostConstruct.class, OrderedTestListener.class); OrderedTestListener listener = this.context.getBean(OrderedTestListener.class); @@ -643,7 +643,7 @@ public void listenersReceiveEarlyEvents() { } @Test - public void missingListenerBeanIgnored() { + void missingListenerBeanIgnored() { load(MissingEventListener.class); context.getBean(UseMissingEventListener.class); context.getBean(ApplicationEventMulticaster.class).multicastEvent(new TestEvent(this)); @@ -697,7 +697,7 @@ public TestConditionEvaluator conditionEvaluator() { static class TestConditionEvaluator { public boolean valid(Double ratio) { - return new Double(42).equals(ratio); + return Double.valueOf(42).equals(ratio); } } } diff --git a/spring-context/src/test/java/org/springframework/context/expression/ApplicationContextExpressionTests.java b/spring-context/src/test/java/org/springframework/context/expression/ApplicationContextExpressionTests.java index e3c9921a504c..657597bc23f9 100644 --- a/spring-context/src/test/java/org/springframework/context/expression/ApplicationContextExpressionTests.java +++ b/spring-context/src/test/java/org/springframework/context/expression/ApplicationContextExpressionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -28,8 +28,6 @@ import java.util.Optional; import java.util.Properties; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.ObjectFactory; @@ -40,7 +38,6 @@ import org.springframework.beans.factory.config.Scope; import org.springframework.beans.factory.config.TypedStringValue; import org.springframework.beans.factory.support.AutowireCandidateQualifier; -import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.testfixture.beans.TestBean; @@ -64,9 +61,6 @@ */ class ApplicationContextExpressionTests { - private static final Log factoryLog = LogFactory.getLog(DefaultListableBeanFactory.class); - - @Test @SuppressWarnings("deprecation") void genericApplicationContext() throws Exception { diff --git a/spring-context/src/test/java/org/springframework/jmx/export/MBeanExporterTests.java b/spring-context/src/test/java/org/springframework/jmx/export/MBeanExporterTests.java index adff3bb372d3..988e068a0b1b 100644 --- a/spring-context/src/test/java/org/springframework/jmx/export/MBeanExporterTests.java +++ b/spring-context/src/test/java/org/springframework/jmx/export/MBeanExporterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -341,10 +341,10 @@ void testWithExposeClassLoader() throws Exception { assertIsRegistered("Bean instance not registered", objectName); - Object result = server.invoke(objectName, "add", new Object[] {new Integer(2), new Integer(3)}, new String[] { + Object result = server.invoke(objectName, "add", new Object[] {2, 3}, new String[] { int.class.getName(), int.class.getName()}); - assertThat(new Integer(5)).as("Incorrect result return from add").isEqualTo(result); + assertThat(Integer.valueOf(5)).as("Incorrect result return from add").isEqualTo(result); assertThat(server.getAttribute(objectName, "Name")).as("Incorrect attribute value").isEqualTo(name); server.setAttribute(objectName, new Attribute("Name", otherName)); @@ -352,7 +352,7 @@ void testWithExposeClassLoader() throws Exception { } @Test - void testBonaFideMBeanIsNotExportedWhenAutodetectIsTotallyTurnedOff() throws Exception { + void testBonaFideMBeanIsNotExportedWhenAutodetectIsTotallyTurnedOff() { BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(Person.class); DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); factory.registerBeanDefinition("^&_invalidObjectName_(*", builder.getBeanDefinition()); diff --git a/spring-context/src/test/java/org/springframework/jmx/export/assembler/AbstractJmxAssemblerTests.java b/spring-context/src/test/java/org/springframework/jmx/export/assembler/AbstractJmxAssemblerTests.java index 26a8b0defffa..c754af69ca15 100644 --- a/spring-context/src/test/java/org/springframework/jmx/export/assembler/AbstractJmxAssemblerTests.java +++ b/spring-context/src/test/java/org/springframework/jmx/export/assembler/AbstractJmxAssemblerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -60,7 +60,7 @@ public void testRegisterOperations() throws Exception { IJmxTestBean bean = getBean(); assertThat(bean).isNotNull(); MBeanInfo inf = getMBeanInfo(); - assertThat(inf.getOperations().length).as("Incorrect number of operations registered").isEqualTo(getExpectedOperationCount()); + assertThat(inf.getOperations()).as("Incorrect number of operations registered").hasSize(getExpectedOperationCount()); } @Test @@ -68,7 +68,7 @@ public void testRegisterAttributes() throws Exception { IJmxTestBean bean = getBean(); assertThat(bean).isNotNull(); MBeanInfo inf = getMBeanInfo(); - assertThat(inf.getAttributes().length).as("Incorrect number of attributes registered").isEqualTo(getExpectedAttributeCount()); + assertThat(inf.getAttributes()).as("Incorrect number of attributes registered").hasSize(getExpectedAttributeCount()); } @Test @@ -81,7 +81,7 @@ public void testGetMBeanInfo() throws Exception { public void testGetMBeanAttributeInfo() throws Exception { ModelMBeanInfo info = getMBeanInfoFromAssembler(); MBeanAttributeInfo[] inf = info.getAttributes(); - assertThat(inf.length).as("Invalid number of Attributes returned").isEqualTo(getExpectedAttributeCount()); + assertThat(inf).as("Invalid number of Attributes returned").hasSize(getExpectedAttributeCount()); for (int x = 0; x < inf.length; x++) { assertThat(inf[x]).as("MBeanAttributeInfo should not be null").isNotNull(); @@ -93,7 +93,7 @@ public void testGetMBeanAttributeInfo() throws Exception { public void testGetMBeanOperationInfo() throws Exception { ModelMBeanInfo info = getMBeanInfoFromAssembler(); MBeanOperationInfo[] inf = info.getOperations(); - assertThat(inf.length).as("Invalid number of Operations returned").isEqualTo(getExpectedOperationCount()); + assertThat(inf).as("Invalid number of Operations returned").hasSize(getExpectedOperationCount()); for (int x = 0; x < inf.length; x++) { assertThat(inf[x]).as("MBeanOperationInfo should not be null").isNotNull(); @@ -128,8 +128,8 @@ public void testGetAttribute() throws Exception { public void testOperationInvocation() throws Exception{ ObjectName objectName = ObjectNameManager.getInstance(getObjectName()); Object result = getServer().invoke(objectName, "add", - new Object[] {new Integer(20), new Integer(30)}, new String[] {"int", "int"}); - assertThat(result).as("Incorrect result").isEqualTo(new Integer(50)); + new Object[] {20, 30}, new String[] {"int", "int"}); + assertThat(result).as("Incorrect result").isEqualTo(50); } @Test @@ -150,12 +150,12 @@ public void testAttributeHasCorrespondingOperations() throws Exception { ModelMBeanOperationInfo get = info.getOperation("getName"); assertThat(get).as("get operation should not be null").isNotNull(); - assertThat(new Integer(4)).as("get operation should have visibility of four").isEqualTo(get.getDescriptor().getFieldValue("visibility")); + assertThat(Integer.valueOf(4)).as("get operation should have visibility of four").isEqualTo(get.getDescriptor().getFieldValue("visibility")); assertThat(get.getDescriptor().getFieldValue("role")).as("get operation should have role \"getter\"").isEqualTo("getter"); ModelMBeanOperationInfo set = info.getOperation("setName"); assertThat(set).as("set operation should not be null").isNotNull(); - assertThat(new Integer(4)).as("set operation should have visibility of four").isEqualTo(set.getDescriptor().getFieldValue("visibility")); + assertThat(Integer.valueOf(4)).as("set operation should have visibility of four").isEqualTo(set.getDescriptor().getFieldValue("visibility")); assertThat(set.getDescriptor().getFieldValue("role")).as("set operation should have role \"setter\"").isEqualTo("setter"); } @@ -163,12 +163,12 @@ public void testAttributeHasCorrespondingOperations() throws Exception { public void testNotificationMetadata() throws Exception { ModelMBeanInfo info = (ModelMBeanInfo) getMBeanInfo(); MBeanNotificationInfo[] notifications = info.getNotifications(); - assertThat(notifications.length).as("Incorrect number of notifications").isEqualTo(1); + assertThat(notifications).as("Incorrect number of notifications").hasSize(1); assertThat(notifications[0].getName()).as("Incorrect notification name").isEqualTo("My Notification"); String[] notifTypes = notifications[0].getNotifTypes(); - assertThat(notifTypes.length).as("Incorrect number of notification types").isEqualTo(2); + assertThat(notifTypes).as("Incorrect number of notification types").hasSize(2); assertThat(notifTypes[0]).as("Notification type.foo not found").isEqualTo("type.foo"); assertThat(notifTypes[1]).as("Notification type.bar not found").isEqualTo("type.bar"); } diff --git a/spring-context/src/test/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessorTests.java b/spring-context/src/test/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessorTests.java index 842910070227..04a08b00e64c 100644 --- a/spring-context/src/test/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessorTests.java +++ b/spring-context/src/test/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -29,9 +29,16 @@ import java.util.Map; import java.util.Properties; import java.util.TimeZone; +import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.converter.ArgumentConversionException; +import org.junit.jupiter.params.converter.ArgumentConverter; +import org.junit.jupiter.params.converter.ConvertWith; +import org.junit.jupiter.params.provider.CsvSource; import org.springframework.aop.framework.ProxyFactory; import org.springframework.aop.scope.ScopedProxyUtils; @@ -60,29 +67,37 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.SoftAssertions.assertSoftly; /** + * Tests for {@link ScheduledAnnotationBeanPostProcessor}. + * * @author Mark Fisher * @author Juergen Hoeller * @author Chris Beams * @author Sam Brannen * @author Stevo Slavić + * @author Victor Brown */ -public class ScheduledAnnotationBeanPostProcessorTests { +class ScheduledAnnotationBeanPostProcessorTests { private final StaticApplicationContext context = new StaticApplicationContext(); @AfterEach - public void closeContextAfterTest() { + void closeContextAfterTest() { context.close(); } - - @Test - public void fixedDelayTask() { + @ParameterizedTest + @CsvSource({ + "FixedDelay, 5000", + "FixedDelayInSeconds, 5000", + "FixedDelayInMinutes, 180000" + }) + void fixedDelayTask(@NameToClass Class beanClass, long expectedInterval) { BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); - BeanDefinition targetDefinition = new RootBeanDefinition(FixedDelayTestBean.class); + BeanDefinition targetDefinition = new RootBeanDefinition(beanClass); context.registerBeanDefinition("postProcessor", processorDefinition); context.registerBeanDefinition("target", targetDefinition); context.refresh(); @@ -96,7 +111,7 @@ public void fixedDelayTask() { @SuppressWarnings("unchecked") List fixedDelayTasks = (List) new DirectFieldAccessor(registrar).getPropertyValue("fixedDelayTasks"); - assertThat(fixedDelayTasks.size()).isEqualTo(1); + assertThat(fixedDelayTasks).hasSize(1); IntervalTask task = fixedDelayTasks.get(0); ScheduledMethodRunnable runnable = (ScheduledMethodRunnable) task.getRunnable(); Object targetObject = runnable.getTarget(); @@ -104,13 +119,18 @@ public void fixedDelayTask() { assertThat(targetObject).isEqualTo(target); assertThat(targetMethod.getName()).isEqualTo("fixedDelay"); assertThat(task.getInitialDelay()).isEqualTo(0L); - assertThat(task.getInterval()).isEqualTo(5000L); + assertThat(task.getInterval()).isEqualTo(expectedInterval); } - @Test - public void fixedRateTask() { + @ParameterizedTest + @CsvSource({ + "FixedRate, 3000", + "FixedRateInSeconds, 5000", + "FixedRateInMinutes, 180000" + }) + void fixedRateTask(@NameToClass Class beanClass, long expectedInterval) { BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); - BeanDefinition targetDefinition = new RootBeanDefinition(FixedRateTestBean.class); + BeanDefinition targetDefinition = new RootBeanDefinition(beanClass); context.registerBeanDefinition("postProcessor", processorDefinition); context.registerBeanDefinition("target", targetDefinition); context.refresh(); @@ -131,14 +151,21 @@ public void fixedRateTask() { Method targetMethod = runnable.getMethod(); assertThat(targetObject).isEqualTo(target); assertThat(targetMethod.getName()).isEqualTo("fixedRate"); - assertThat(task.getInitialDelay()).isEqualTo(0L); - assertThat(task.getInterval()).isEqualTo(3000L); + assertSoftly(softly -> { + softly.assertThat(task.getInitialDelay()).as("initial delay").isEqualTo(0); + softly.assertThat(task.getInterval()).as("interval").isEqualTo(expectedInterval); + }); } - @Test - public void fixedRateTaskWithInitialDelay() { + @ParameterizedTest + @CsvSource({ + "FixedRateWithInitialDelay, 1000, 3000", + "FixedRateWithInitialDelayInSeconds, 5000, 3000", + "FixedRateWithInitialDelayInMinutes, 60000, 180000" + }) + void fixedRateTaskWithInitialDelay(@NameToClass Class beanClass, long expectedInitialDelay, long expectedInterval) { BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); - BeanDefinition targetDefinition = new RootBeanDefinition(FixedRateWithInitialDelayTestBean.class); + BeanDefinition targetDefinition = new RootBeanDefinition(beanClass); context.registerBeanDefinition("postProcessor", processorDefinition); context.registerBeanDefinition("target", targetDefinition); context.refresh(); @@ -159,40 +186,42 @@ public void fixedRateTaskWithInitialDelay() { Method targetMethod = runnable.getMethod(); assertThat(targetObject).isEqualTo(target); assertThat(targetMethod.getName()).isEqualTo("fixedRate"); - assertThat(task.getInitialDelay()).isEqualTo(1000L); - assertThat(task.getInterval()).isEqualTo(3000L); + assertSoftly(softly -> { + softly.assertThat(task.getInitialDelay()).as("initial delay").isEqualTo(expectedInitialDelay); + softly.assertThat(task.getInterval()).as("interval").isEqualTo(expectedInterval); + }); } @Test - public void severalFixedRatesWithRepeatedScheduledAnnotation() { + void severalFixedRatesWithRepeatedScheduledAnnotation() { BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); BeanDefinition targetDefinition = new RootBeanDefinition(SeveralFixedRatesWithRepeatedScheduledAnnotationTestBean.class); severalFixedRates(context, processorDefinition, targetDefinition); } @Test - public void severalFixedRatesWithSchedulesContainerAnnotation() { + void severalFixedRatesWithSchedulesContainerAnnotation() { BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); BeanDefinition targetDefinition = new RootBeanDefinition(SeveralFixedRatesWithSchedulesContainerAnnotationTestBean.class); severalFixedRates(context, processorDefinition, targetDefinition); } @Test - public void severalFixedRatesOnBaseClass() { + void severalFixedRatesOnBaseClass() { BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); BeanDefinition targetDefinition = new RootBeanDefinition(FixedRatesSubBean.class); severalFixedRates(context, processorDefinition, targetDefinition); } @Test - public void severalFixedRatesOnDefaultMethod() { + void severalFixedRatesOnDefaultMethod() { BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); BeanDefinition targetDefinition = new RootBeanDefinition(FixedRatesDefaultBean.class); severalFixedRates(context, processorDefinition, targetDefinition); } @Test - public void severalFixedRatesAgainstNestedCglibProxy() { + void severalFixedRatesAgainstNestedCglibProxy() { BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); BeanDefinition targetDefinition = new RootBeanDefinition(SeveralFixedRatesWithRepeatedScheduledAnnotationTestBean.class); targetDefinition.setFactoryMethodName("nestedProxy"); @@ -235,7 +264,7 @@ private void severalFixedRates(StaticApplicationContext context, } @Test - public void cronTask() { + void cronTask() { BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); BeanDefinition targetDefinition = new RootBeanDefinition(CronTestBean.class); context.registerBeanDefinition("postProcessor", processorDefinition); @@ -262,7 +291,7 @@ public void cronTask() { } @Test - public void cronTaskWithZone() { + void cronTaskWithZone() { BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); BeanDefinition targetDefinition = new RootBeanDefinition(CronWithTimezoneTestBean.class); context.registerBeanDefinition("postProcessor", processorDefinition); @@ -308,7 +337,7 @@ public void cronTaskWithZone() { } @Test - public void cronTaskWithInvalidZone() { + void cronTaskWithInvalidZone() { BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); BeanDefinition targetDefinition = new RootBeanDefinition(CronWithInvalidTimezoneTestBean.class); context.registerBeanDefinition("postProcessor", processorDefinition); @@ -318,7 +347,7 @@ public void cronTaskWithInvalidZone() { } @Test - public void cronTaskWithMethodValidation() { + void cronTaskWithMethodValidation() { BeanDefinition validationDefinition = new RootBeanDefinition(MethodValidationPostProcessor.class); BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); BeanDefinition targetDefinition = new RootBeanDefinition(CronTestBean.class); @@ -330,7 +359,7 @@ public void cronTaskWithMethodValidation() { } @Test - public void cronTaskWithScopedProxy() { + void cronTaskWithScopedProxy() { BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); context.registerBeanDefinition("postProcessor", processorDefinition); new AnnotatedBeanDefinitionReader(context).register(ProxiedCronTestBean.class, ProxiedCronTestBeanDependent.class); @@ -355,7 +384,7 @@ public void cronTaskWithScopedProxy() { } @Test - public void metaAnnotationWithFixedRate() { + void metaAnnotationWithFixedRate() { BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); BeanDefinition targetDefinition = new RootBeanDefinition(MetaAnnotationFixedRateTestBean.class); context.registerBeanDefinition("postProcessor", processorDefinition); @@ -382,7 +411,7 @@ public void metaAnnotationWithFixedRate() { } @Test - public void composedAnnotationWithInitialDelayAndFixedRate() { + void composedAnnotationWithInitialDelayAndFixedRate() { BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); BeanDefinition targetDefinition = new RootBeanDefinition(ComposedAnnotationFixedRateTestBean.class); context.registerBeanDefinition("postProcessor", processorDefinition); @@ -410,7 +439,7 @@ public void composedAnnotationWithInitialDelayAndFixedRate() { } @Test - public void metaAnnotationWithCronExpression() { + void metaAnnotationWithCronExpression() { BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); BeanDefinition targetDefinition = new RootBeanDefinition(MetaAnnotationCronTestBean.class); context.registerBeanDefinition("postProcessor", processorDefinition); @@ -437,7 +466,7 @@ public void metaAnnotationWithCronExpression() { } @Test - public void propertyPlaceholderWithCron() { + void propertyPlaceholderWithCron() { String businessHoursCronExpression = "0 0 9-17 * * MON-FRI"; BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); BeanDefinition placeholderDefinition = new RootBeanDefinition(PropertySourcesPlaceholderConfigurer.class); @@ -470,7 +499,7 @@ public void propertyPlaceholderWithCron() { } @Test - public void propertyPlaceholderWithInactiveCron() { + void propertyPlaceholderWithInactiveCron() { String businessHoursCronExpression = "-"; BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); BeanDefinition placeholderDefinition = new RootBeanDefinition(PropertySourcesPlaceholderConfigurer.class); @@ -487,24 +516,23 @@ public void propertyPlaceholderWithInactiveCron() { assertThat(postProcessor.getScheduledTasks().isEmpty()).isTrue(); } - @Test - public void propertyPlaceholderWithFixedDelayInMillis() { - propertyPlaceholderWithFixedDelay(false); - } + @ParameterizedTest + @CsvSource({ + "PropertyPlaceholderWithFixedDelay, 5000, 1000, 5000, 1000", + "PropertyPlaceholderWithFixedDelay, PT5S, PT1S, 5000, 1000", + "PropertyPlaceholderWithFixedDelayInSeconds, 5000, 1000, 5000000, 1000000", + "PropertyPlaceholderWithFixedDelayInSeconds, PT5S, PT1S, 5000, 1000" + }) + void propertyPlaceholderWithFixedDelay(@NameToClass Class beanClass, String fixedDelay, String initialDelay, + long expectedInterval, long expectedInitialDelay) { - @Test - public void propertyPlaceholderWithFixedDelayInDuration() { - propertyPlaceholderWithFixedDelay(true); - } - - private void propertyPlaceholderWithFixedDelay(boolean durationFormat) { BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); BeanDefinition placeholderDefinition = new RootBeanDefinition(PropertySourcesPlaceholderConfigurer.class); Properties properties = new Properties(); - properties.setProperty("fixedDelay", (durationFormat ? "PT5S" : "5000")); - properties.setProperty("initialDelay", (durationFormat ? "PT1S" : "1000")); + properties.setProperty("fixedDelay", fixedDelay); + properties.setProperty("initialDelay", initialDelay); placeholderDefinition.getPropertyValues().addPropertyValue("properties", properties); - BeanDefinition targetDefinition = new RootBeanDefinition(PropertyPlaceholderWithFixedDelayTestBean.class); + BeanDefinition targetDefinition = new RootBeanDefinition(beanClass); context.registerBeanDefinition("postProcessor", processorDefinition); context.registerBeanDefinition("placeholder", placeholderDefinition); context.registerBeanDefinition("target", targetDefinition); @@ -526,28 +554,29 @@ private void propertyPlaceholderWithFixedDelay(boolean durationFormat) { Method targetMethod = runnable.getMethod(); assertThat(targetObject).isEqualTo(target); assertThat(targetMethod.getName()).isEqualTo("fixedDelay"); - assertThat(task.getInitialDelay()).isEqualTo(1000L); - assertThat(task.getInterval()).isEqualTo(5000L); + assertSoftly(softly -> { + softly.assertThat(task.getInitialDelay()).as("initial delay").isEqualTo(expectedInitialDelay); + softly.assertThat(task.getInterval()).as("interval").isEqualTo(expectedInterval); + }); } - @Test - public void propertyPlaceholderWithFixedRateInMillis() { - propertyPlaceholderWithFixedRate(false); - } + @ParameterizedTest + @CsvSource({ + "PropertyPlaceholderWithFixedRate, 3000, 1000, 3000, 1000", + "PropertyPlaceholderWithFixedRate, PT3S, PT1S, 3000, 1000", + "PropertyPlaceholderWithFixedRateInSeconds, 3000, 1000, 3000000, 1000000", + "PropertyPlaceholderWithFixedRateInSeconds, PT3S, PT1S, 3000, 1000" + }) + void propertyPlaceholderWithFixedRate(@NameToClass Class beanClass, String fixedRate, String initialDelay, + long expectedInterval, long expectedInitialDelay) { - @Test - public void propertyPlaceholderWithFixedRateInDuration() { - propertyPlaceholderWithFixedRate(true); - } - - private void propertyPlaceholderWithFixedRate(boolean durationFormat) { BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); BeanDefinition placeholderDefinition = new RootBeanDefinition(PropertySourcesPlaceholderConfigurer.class); Properties properties = new Properties(); - properties.setProperty("fixedRate", (durationFormat ? "PT3S" : "3000")); - properties.setProperty("initialDelay", (durationFormat ? "PT1S" : "1000")); + properties.setProperty("fixedRate", fixedRate); + properties.setProperty("initialDelay", initialDelay); placeholderDefinition.getPropertyValues().addPropertyValue("properties", properties); - BeanDefinition targetDefinition = new RootBeanDefinition(PropertyPlaceholderWithFixedRateTestBean.class); + BeanDefinition targetDefinition = new RootBeanDefinition(beanClass); context.registerBeanDefinition("postProcessor", processorDefinition); context.registerBeanDefinition("placeholder", placeholderDefinition); context.registerBeanDefinition("target", targetDefinition); @@ -569,12 +598,14 @@ private void propertyPlaceholderWithFixedRate(boolean durationFormat) { Method targetMethod = runnable.getMethod(); assertThat(targetObject).isEqualTo(target); assertThat(targetMethod.getName()).isEqualTo("fixedRate"); - assertThat(task.getInitialDelay()).isEqualTo(1000L); - assertThat(task.getInterval()).isEqualTo(3000L); + assertSoftly(softly -> { + softly.assertThat(task.getInitialDelay()).as("initial delay").isEqualTo(expectedInitialDelay); + softly.assertThat(task.getInterval()).as("interval").isEqualTo(expectedInterval); + }); } @Test - public void expressionWithCron() { + void expressionWithCron() { String businessHoursCronExpression = "0 0 9-17 * * MON-FRI"; BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); BeanDefinition targetDefinition = new RootBeanDefinition(ExpressionWithCronTestBean.class); @@ -605,7 +636,7 @@ public void expressionWithCron() { } @Test - public void propertyPlaceholderForMetaAnnotation() { + void propertyPlaceholderForMetaAnnotation() { String businessHoursCronExpression = "0 0 9-17 * * MON-FRI"; BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); BeanDefinition placeholderDefinition = new RootBeanDefinition(PropertySourcesPlaceholderConfigurer.class); @@ -638,7 +669,7 @@ public void propertyPlaceholderForMetaAnnotation() { } @Test - public void nonVoidReturnType() { + void nonVoidReturnType() { BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); BeanDefinition targetDefinition = new RootBeanDefinition(NonVoidReturnTypeTestBean.class); context.registerBeanDefinition("postProcessor", processorDefinition); @@ -665,7 +696,7 @@ public void nonVoidReturnType() { } @Test - public void emptyAnnotation() { + void emptyAnnotation() { BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); BeanDefinition targetDefinition = new RootBeanDefinition(EmptyAnnotationTestBean.class); context.registerBeanDefinition("postProcessor", processorDefinition); @@ -675,7 +706,7 @@ public void emptyAnnotation() { } @Test - public void invalidCron() throws Throwable { + void invalidCron() throws Throwable { BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); BeanDefinition targetDefinition = new RootBeanDefinition(InvalidCronTestBean.class); context.registerBeanDefinition("postProcessor", processorDefinition); @@ -685,7 +716,7 @@ public void invalidCron() throws Throwable { } @Test - public void nonEmptyParamList() { + void nonEmptyParamList() { BeanDefinition processorDefinition = new RootBeanDefinition(ScheduledAnnotationBeanPostProcessor.class); BeanDefinition targetDefinition = new RootBeanDefinition(NonEmptyParamListTestBean.class); context.registerBeanDefinition("postProcessor", processorDefinition); @@ -695,26 +726,68 @@ public void nonEmptyParamList() { } - static class FixedDelayTestBean { + static class FixedDelay { @Scheduled(fixedDelay = 5000) - public void fixedDelay() { + void fixedDelay() { + } + } + + static class FixedDelayInSeconds { + + @Scheduled(fixedDelay = 5, timeUnit = TimeUnit.SECONDS) + void fixedDelay() { + } + } + + static class FixedDelayInMinutes { + + @Scheduled(fixedDelay = 3, timeUnit = TimeUnit.MINUTES) + void fixedDelay() { } } - static class FixedRateTestBean { + static class FixedRate { @Scheduled(fixedRate = 3000) - public void fixedRate() { + void fixedRate() { + } + } + + static class FixedRateInSeconds { + + @Scheduled(fixedRate = 5, timeUnit = TimeUnit.SECONDS) + void fixedRate() { } } + static class FixedRateInMinutes { + + @Scheduled(fixedRate = 3, timeUnit = TimeUnit.MINUTES) + void fixedRate() { + } + } - static class FixedRateWithInitialDelayTestBean { + + static class FixedRateWithInitialDelay { @Scheduled(fixedRate = 3000, initialDelay = 1000) - public void fixedRate() { + void fixedRate() { + } + } + + static class FixedRateWithInitialDelayInSeconds { + + @Scheduled(fixedRate = 3, initialDelay = 5, timeUnit = TimeUnit.SECONDS) + void fixedRate() { + } + } + + static class FixedRateWithInitialDelayInMinutes { + + @Scheduled(fixedRate = 3, initialDelay = 1, timeUnit = TimeUnit.MINUTES) + void fixedRate() { } } @@ -722,7 +795,7 @@ public void fixedRate() { static class SeveralFixedRatesWithSchedulesContainerAnnotationTestBean { @Schedules({@Scheduled(fixedRate = 4000), @Scheduled(fixedRate = 4000, initialDelay = 2000)}) - public void fixedRate() { + void fixedRate() { } } @@ -731,7 +804,7 @@ static class SeveralFixedRatesWithRepeatedScheduledAnnotationTestBean { @Scheduled(fixedRate = 4000) @Scheduled(fixedRate = 4000, initialDelay = 2000) - public void fixedRate() { + void fixedRate() { } static SeveralFixedRatesWithRepeatedScheduledAnnotationTestBean nestedProxy() { @@ -748,7 +821,7 @@ static class FixedRatesBaseBean { @Scheduled(fixedRate = 4000) @Scheduled(fixedRate = 4000, initialDelay = 2000) - public void fixedRate() { + void fixedRate() { } } @@ -792,7 +865,7 @@ protected void cron() throws IOException { static class CronWithInvalidTimezoneTestBean { @Scheduled(cron = "0 0 0-4,6-23 * * ?", zone = "FOO") - public void cron() throws IOException { + void cron() throws IOException { throw new IOException("no no no"); } } @@ -803,7 +876,7 @@ public void cron() throws IOException { static class ProxiedCronTestBean { @Scheduled(cron = "*/7 * * * * ?") - public void cron() throws IOException { + void cron() throws IOException { throw new IOException("no no no"); } } @@ -811,7 +884,7 @@ public void cron() throws IOException { static class ProxiedCronTestBeanDependent { - public ProxiedCronTestBeanDependent(ProxiedCronTestBean testBean) { + ProxiedCronTestBeanDependent(ProxiedCronTestBean testBean) { } } @@ -819,7 +892,7 @@ public ProxiedCronTestBeanDependent(ProxiedCronTestBean testBean) { static class NonVoidReturnTypeTestBean { @Scheduled(cron = "0 0 9-17 * * MON-FRI") - public String cron() { + String cron() { return "oops"; } } @@ -828,7 +901,7 @@ public String cron() { static class EmptyAnnotationTestBean { @Scheduled - public void invalid() { + void invalid() { } } @@ -836,7 +909,7 @@ public void invalid() { static class InvalidCronTestBean { @Scheduled(cron = "abc") - public void invalid() { + void invalid() { } } @@ -844,7 +917,7 @@ public void invalid() { static class NonEmptyParamListTestBean { @Scheduled(fixedRate = 3000) - public void invalid(String oops) { + void invalid(String oops) { } } @@ -876,7 +949,7 @@ public void invalid(String oops) { static class MetaAnnotationFixedRateTestBean { @EveryFiveSeconds - public void checkForUpdates() { + void checkForUpdates() { } } @@ -884,7 +957,7 @@ public void checkForUpdates() { static class ComposedAnnotationFixedRateTestBean { @WaitASec(fixedRate = 5000) - public void checkForUpdates() { + void checkForUpdates() { } } @@ -892,7 +965,7 @@ public void checkForUpdates() { static class MetaAnnotationCronTestBean { @Hourly - public void generateReport() { + void generateReport() { } } @@ -900,23 +973,37 @@ public void generateReport() { static class PropertyPlaceholderWithCronTestBean { @Scheduled(cron = "${schedules.businessHours}") - public void x() { + void x() { } } - static class PropertyPlaceholderWithFixedDelayTestBean { + static class PropertyPlaceholderWithFixedDelay { @Scheduled(fixedDelayString = "${fixedDelay}", initialDelayString = "${initialDelay}") - public void fixedDelay() { + void fixedDelay() { } } + static class PropertyPlaceholderWithFixedDelayInSeconds { - static class PropertyPlaceholderWithFixedRateTestBean { + @Scheduled(fixedDelayString = "${fixedDelay}", initialDelayString = "${initialDelay}", timeUnit = TimeUnit.SECONDS) + void fixedDelay() { + } + } + + + static class PropertyPlaceholderWithFixedRate { @Scheduled(fixedRateString = "${fixedRate}", initialDelayString = "${initialDelay}") - public void fixedRate() { + void fixedRate() { + } + } + + static class PropertyPlaceholderWithFixedRateInSeconds { + + @Scheduled(fixedRateString = "${fixedRate}", initialDelayString = "${initialDelay}", timeUnit = TimeUnit.SECONDS) + void fixedRate() { } } @@ -924,7 +1011,7 @@ public void fixedRate() { static class ExpressionWithCronTestBean { @Scheduled(cron = "#{schedules.businessHours}") - public void x() { + void x() { } } @@ -939,7 +1026,24 @@ public void x() { static class PropertyPlaceholderMetaAnnotationTestBean { @BusinessHours - public void y() { + void y() { + } + } + + @Retention(RetentionPolicy.RUNTIME) + @ConvertWith(NameToClass.Converter.class) + private @interface NameToClass { + class Converter implements ArgumentConverter { + @Override + public Class convert(Object beanClassName, ParameterContext context) throws ArgumentConversionException { + try { + String name = getClass().getEnclosingClass().getEnclosingClass().getName() + "$" + beanClassName; + return getClass().getClassLoader().loadClass(name); + } + catch (Exception ex) { + throw new ArgumentConversionException("Failed to convert class name to Class", ex); + } + } } } diff --git a/spring-context/src/test/java/org/springframework/scripting/support/ScriptFactoryPostProcessorTests.java b/spring-context/src/test/java/org/springframework/scripting/support/ScriptFactoryPostProcessorTests.java index 16253239fa74..d6702d317db7 100644 --- a/spring-context/src/test/java/org/springframework/scripting/support/ScriptFactoryPostProcessorTests.java +++ b/spring-context/src/test/java/org/springframework/scripting/support/ScriptFactoryPostProcessorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -41,7 +41,7 @@ * @author Chris Beams */ @EnabledForTestGroups(LONG_RUNNING) -public class ScriptFactoryPostProcessorTests { +class ScriptFactoryPostProcessorTests { private static final String MESSAGE_TEXT = "Bingo"; @@ -79,18 +79,18 @@ public class ScriptFactoryPostProcessorTests { @Test - public void testDoesNothingWhenPostProcessingNonScriptFactoryTypeBeforeInstantiation() throws Exception { + void testDoesNothingWhenPostProcessingNonScriptFactoryTypeBeforeInstantiation() { assertThat(new ScriptFactoryPostProcessor().postProcessBeforeInstantiation(getClass(), "a.bean")).isNull(); } @Test - public void testThrowsExceptionIfGivenNonAbstractBeanFactoryImplementation() throws Exception { + void testThrowsExceptionIfGivenNonAbstractBeanFactoryImplementation() { assertThatIllegalStateException().isThrownBy(() -> new ScriptFactoryPostProcessor().setBeanFactory(mock(BeanFactory.class))); } @Test - public void testChangeScriptWithRefreshableBeanFunctionality() throws Exception { + void testChangeScriptWithRefreshableBeanFunctionality() throws Exception { BeanDefinition processorBeanDefinition = createScriptFactoryPostProcessor(true); BeanDefinition scriptedBeanDefinition = createScriptedGroovyBean(); @@ -111,7 +111,7 @@ public void testChangeScriptWithRefreshableBeanFunctionality() throws Exception } @Test - public void testChangeScriptWithNoRefreshableBeanFunctionality() throws Exception { + void testChangeScriptWithNoRefreshableBeanFunctionality() throws Exception { BeanDefinition processorBeanDefinition = createScriptFactoryPostProcessor(false); BeanDefinition scriptedBeanDefinition = createScriptedGroovyBean(); @@ -131,7 +131,7 @@ public void testChangeScriptWithNoRefreshableBeanFunctionality() throws Exceptio } @Test - public void testRefreshedScriptReferencePropagatesToCollaborators() throws Exception { + void testRefreshedScriptReferencePropagatesToCollaborators() throws Exception { BeanDefinition processorBeanDefinition = createScriptFactoryPostProcessor(true); BeanDefinition scriptedBeanDefinition = createScriptedGroovyBean(); BeanDefinitionBuilder collaboratorBuilder = BeanDefinitionBuilder.rootBeanDefinition(DefaultMessengerService.class); @@ -159,7 +159,7 @@ public void testRefreshedScriptReferencePropagatesToCollaborators() throws Excep } @Test - public void testReferencesAcrossAContainerHierarchy() throws Exception { + void testReferencesAcrossAContainerHierarchy() throws Exception { GenericApplicationContext businessContext = new GenericApplicationContext(); businessContext.registerBeanDefinition("messenger", BeanDefinitionBuilder.rootBeanDefinition(StubMessenger.class).getBeanDefinition()); businessContext.refresh(); @@ -175,13 +175,13 @@ public void testReferencesAcrossAContainerHierarchy() throws Exception { } @Test - public void testScriptHavingAReferenceToAnotherBean() throws Exception { + void testScriptHavingAReferenceToAnotherBean() throws Exception { // just tests that the (singleton) script-backed bean is able to be instantiated with references to its collaborators new ClassPathXmlApplicationContext("org/springframework/scripting/support/groovyReferences.xml"); } @Test - public void testForRefreshedScriptHavingErrorPickedUpOnFirstCall() throws Exception { + void testForRefreshedScriptHavingErrorPickedUpOnFirstCall() throws Exception { BeanDefinition processorBeanDefinition = createScriptFactoryPostProcessor(true); BeanDefinition scriptedBeanDefinition = createScriptedGroovyBean(); BeanDefinitionBuilder collaboratorBuilder = BeanDefinitionBuilder.rootBeanDefinition(DefaultMessengerService.class); @@ -202,13 +202,12 @@ public void testForRefreshedScriptHavingErrorPickedUpOnFirstCall() throws Except // needs The Sundays compiler; must NOT throw any exception here... source.setScript("I keep hoping you are the same as me, and I'll send you letters and come to your house for tea"); Messenger refreshedMessenger = (Messenger) ctx.getBean(MESSENGER_BEAN_NAME); - assertThatExceptionOfType(FatalBeanException.class).isThrownBy(() -> - refreshedMessenger.getMessage()) + assertThatExceptionOfType(FatalBeanException.class).isThrownBy(refreshedMessenger::getMessage) .matches(ex -> ex.contains(ScriptCompilationException.class)); } @Test - public void testPrototypeScriptedBean() throws Exception { + void testPrototypeScriptedBean() throws Exception { GenericApplicationContext ctx = new GenericApplicationContext(); ctx.registerBeanDefinition("messenger", BeanDefinitionBuilder.rootBeanDefinition(StubMessenger.class).getBeanDefinition()); @@ -236,7 +235,7 @@ private static StaticScriptSource getScriptSource(GenericApplicationContext ctx) private static BeanDefinition createScriptFactoryPostProcessor(boolean isRefreshable) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(ScriptFactoryPostProcessor.class); if (isRefreshable) { - builder.addPropertyValue("defaultRefreshCheckDelay", new Long(1)); + builder.addPropertyValue("defaultRefreshCheckDelay", 1L); } return builder.getBeanDefinition(); } diff --git a/spring-context/src/test/java/org/springframework/validation/DataBinderFieldAccessTests.java b/spring-context/src/test/java/org/springframework/validation/DataBinderFieldAccessTests.java index 602454760041..f8ffc26ab8ad 100644 --- a/spring-context/src/test/java/org/springframework/validation/DataBinderFieldAccessTests.java +++ b/spring-context/src/test/java/org/springframework/validation/DataBinderFieldAccessTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -36,17 +36,17 @@ * @author Stephane Nicoll * @since 07.03.2006 */ -public class DataBinderFieldAccessTests { +class DataBinderFieldAccessTests { @Test - public void bindingNoErrors() throws Exception { + void bindingNoErrors() throws Exception { FieldAccessBean rod = new FieldAccessBean(); DataBinder binder = new DataBinder(rod, "person"); assertThat(binder.isIgnoreUnknownFields()).isTrue(); binder.initDirectFieldAccess(); MutablePropertyValues pvs = new MutablePropertyValues(); pvs.addPropertyValue(new PropertyValue("name", "Rod")); - pvs.addPropertyValue(new PropertyValue("age", new Integer(32))); + pvs.addPropertyValue(new PropertyValue("age", 32)); pvs.addPropertyValue(new PropertyValue("nonExisting", "someValue")); binder.bind(pvs); @@ -62,21 +62,21 @@ public void bindingNoErrors() throws Exception { } @Test - public void bindingNoErrorsNotIgnoreUnknown() throws Exception { + void bindingNoErrorsNotIgnoreUnknown() throws Exception { FieldAccessBean rod = new FieldAccessBean(); DataBinder binder = new DataBinder(rod, "person"); binder.initDirectFieldAccess(); binder.setIgnoreUnknownFields(false); MutablePropertyValues pvs = new MutablePropertyValues(); pvs.addPropertyValue(new PropertyValue("name", "Rod")); - pvs.addPropertyValue(new PropertyValue("age", new Integer(32))); + pvs.addPropertyValue(new PropertyValue("age", 32)); pvs.addPropertyValue(new PropertyValue("nonExisting", "someValue")); assertThatExceptionOfType(NotWritablePropertyException.class).isThrownBy(() -> binder.bind(pvs)); } @Test - public void bindingWithErrors() throws Exception { + void bindingWithErrors() throws Exception { FieldAccessBean rod = new FieldAccessBean(); DataBinder binder = new DataBinder(rod, "person"); binder.initDirectFieldAccess(); @@ -105,7 +105,7 @@ public void bindingWithErrors() throws Exception { } @Test - public void nestedBindingWithDefaultConversionNoErrors() throws Exception { + void nestedBindingWithDefaultConversionNoErrors() throws Exception { FieldAccessBean rod = new FieldAccessBean(); DataBinder binder = new DataBinder(rod, "person"); assertThat(binder.isIgnoreUnknownFields()).isTrue(); @@ -122,7 +122,7 @@ public void nestedBindingWithDefaultConversionNoErrors() throws Exception { } @Test - public void nestedBindingWithDisabledAutoGrow() throws Exception { + void nestedBindingWithDisabledAutoGrow() throws Exception { FieldAccessBean rod = new FieldAccessBean(); DataBinder binder = new DataBinder(rod, "person"); binder.setAutoGrowNestedPaths(false); @@ -135,7 +135,7 @@ public void nestedBindingWithDisabledAutoGrow() throws Exception { } @Test - public void bindingWithErrorsAndCustomEditors() throws Exception { + void bindingWithErrorsAndCustomEditors() throws Exception { FieldAccessBean rod = new FieldAccessBean(); DataBinder binder = new DataBinder(rod, "person"); binder.initDirectFieldAccess(); diff --git a/spring-context/src/test/java/org/springframework/validation/DataBinderTests.java b/spring-context/src/test/java/org/springframework/validation/DataBinderTests.java index 420e17d9a3fa..a820d40a6a43 100644 --- a/spring-context/src/test/java/org/springframework/validation/DataBinderTests.java +++ b/spring-context/src/test/java/org/springframework/validation/DataBinderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -77,10 +77,10 @@ * @author Rob Harrop * @author Kazuki Shimizu */ -public class DataBinderTests { +class DataBinderTests { @Test - public void testBindingNoErrors() throws BindException { + void testBindingNoErrors() throws BindException { TestBean rod = new TestBean(); DataBinder binder = new DataBinder(rod, "person"); assertThat(binder.isIgnoreUnknownFields()).isTrue(); @@ -115,7 +115,7 @@ public void testBindingNoErrors() throws BindException { } @Test - public void testBindingWithDefaultConversionNoErrors() throws BindException { + void testBindingWithDefaultConversionNoErrors() throws BindException { TestBean rod = new TestBean(); DataBinder binder = new DataBinder(rod, "person"); assertThat(binder.isIgnoreUnknownFields()).isTrue(); @@ -131,7 +131,7 @@ public void testBindingWithDefaultConversionNoErrors() throws BindException { } @Test - public void testNestedBindingWithDefaultConversionNoErrors() throws BindException { + void testNestedBindingWithDefaultConversionNoErrors() throws BindException { TestBean rod = new TestBean(new TestBean()); DataBinder binder = new DataBinder(rod, "person"); assertThat(binder.isIgnoreUnknownFields()).isTrue(); @@ -147,7 +147,7 @@ public void testNestedBindingWithDefaultConversionNoErrors() throws BindExceptio } @Test - public void testBindingNoErrorsNotIgnoreUnknown() { + void testBindingNoErrorsNotIgnoreUnknown() { TestBean rod = new TestBean(); DataBinder binder = new DataBinder(rod, "person"); binder.setIgnoreUnknownFields(false); @@ -160,7 +160,7 @@ public void testBindingNoErrorsNotIgnoreUnknown() { } @Test - public void testBindingNoErrorsWithInvalidField() { + void testBindingNoErrorsWithInvalidField() { TestBean rod = new TestBean(); DataBinder binder = new DataBinder(rod, "person"); MutablePropertyValues pvs = new MutablePropertyValues(); @@ -171,7 +171,7 @@ public void testBindingNoErrorsWithInvalidField() { } @Test - public void testBindingNoErrorsWithIgnoreInvalid() { + void testBindingNoErrorsWithIgnoreInvalid() { TestBean rod = new TestBean(); DataBinder binder = new DataBinder(rod, "person"); binder.setIgnoreInvalidFields(true); @@ -183,7 +183,7 @@ public void testBindingNoErrorsWithIgnoreInvalid() { } @Test - public void testBindingWithErrors() { + void testBindingWithErrors() { TestBean rod = new TestBean(); DataBinder binder = new DataBinder(rod, "person"); MutablePropertyValues pvs = new MutablePropertyValues(); @@ -245,7 +245,7 @@ public void testBindingWithErrors() { } @Test - public void testBindingWithSystemFieldError() { + void testBindingWithSystemFieldError() { TestBean rod = new TestBean(); DataBinder binder = new DataBinder(rod, "person"); MutablePropertyValues pvs = new MutablePropertyValues(); @@ -257,7 +257,7 @@ public void testBindingWithSystemFieldError() { } @Test - public void testBindingWithErrorsAndCustomEditors() { + void testBindingWithErrorsAndCustomEditors() { TestBean rod = new TestBean(); DataBinder binder = new DataBinder(rod, "person"); binder.registerCustomEditor(String.class, "touchy", new PropertyEditorSupport() { @@ -325,7 +325,7 @@ public String getAsText() { } @Test - public void testBindingWithCustomEditorOnObjectField() { + void testBindingWithCustomEditorOnObjectField() { BeanWithObjectProperty tb = new BeanWithObjectProperty(); DataBinder binder = new DataBinder(tb); binder.registerCustomEditor(Integer.class, "object", new CustomNumberEditor(Integer.class, true)); @@ -336,7 +336,7 @@ public void testBindingWithCustomEditorOnObjectField() { } @Test - public void testBindingWithFormatter() { + void testBindingWithFormatter() { TestBean tb = new TestBean(); DataBinder binder = new DataBinder(tb); FormattingConversionService conversionService = new FormattingConversionService(); @@ -349,18 +349,18 @@ public void testBindingWithFormatter() { LocaleContextHolder.setLocale(Locale.GERMAN); try { binder.bind(pvs); - assertThat(tb.getMyFloat()).isEqualTo(new Float(1.2)); + assertThat(tb.getMyFloat()).isEqualTo(Float.valueOf(1.2f)); assertThat(binder.getBindingResult().getFieldValue("myFloat")).isEqualTo("1,2"); PropertyEditor editor = binder.getBindingResult().findEditor("myFloat", Float.class); assertThat(editor).isNotNull(); - editor.setValue(new Float(1.4)); + editor.setValue(1.4f); assertThat(editor.getAsText()).isEqualTo("1,4"); editor = binder.getBindingResult().findEditor("myFloat", null); assertThat(editor).isNotNull(); editor.setAsText("1,6"); - assertThat(editor.getValue()).isEqualTo(new Float(1.6)); + assertThat(editor.getValue()).isEqualTo(1.6f); } finally { LocaleContextHolder.resetLocaleContext(); @@ -368,7 +368,7 @@ public void testBindingWithFormatter() { } @Test - public void testBindingErrorWithFormatter() { + void testBindingErrorWithFormatter() { TestBean tb = new TestBean(); DataBinder binder = new DataBinder(tb); FormattingConversionService conversionService = new FormattingConversionService(); @@ -381,7 +381,7 @@ public void testBindingErrorWithFormatter() { LocaleContextHolder.setLocale(Locale.GERMAN); try { binder.bind(pvs); - assertThat(tb.getMyFloat()).isEqualTo(new Float(0.0)); + assertThat(tb.getMyFloat()).isEqualTo(Float.valueOf(0.0f)); assertThat(binder.getBindingResult().getFieldValue("myFloat")).isEqualTo("1x2"); assertThat(binder.getBindingResult().hasFieldErrors("myFloat")).isTrue(); } @@ -391,7 +391,7 @@ public void testBindingErrorWithFormatter() { } @Test - public void testBindingErrorWithParseExceptionFromFormatter() { + void testBindingErrorWithParseExceptionFromFormatter() { TestBean tb = new TestBean(); DataBinder binder = new DataBinder(tb); FormattingConversionService conversionService = new FormattingConversionService(); @@ -419,7 +419,7 @@ public String print(String object, Locale locale) { } @Test - public void testBindingErrorWithRuntimeExceptionFromFormatter() { + void testBindingErrorWithRuntimeExceptionFromFormatter() { TestBean tb = new TestBean(); DataBinder binder = new DataBinder(tb); FormattingConversionService conversionService = new FormattingConversionService(); @@ -447,7 +447,7 @@ public String print(String object, Locale locale) { } @Test - public void testBindingWithFormatterAgainstList() { + void testBindingWithFormatterAgainstList() { BeanWithIntegerList tb = new BeanWithIntegerList(); DataBinder binder = new DataBinder(tb); FormattingConversionService conversionService = new FormattingConversionService(); @@ -469,7 +469,7 @@ public void testBindingWithFormatterAgainstList() { } @Test - public void testBindingErrorWithFormatterAgainstList() { + void testBindingErrorWithFormatterAgainstList() { BeanWithIntegerList tb = new BeanWithIntegerList(); DataBinder binder = new DataBinder(tb); FormattingConversionService conversionService = new FormattingConversionService(); @@ -492,7 +492,7 @@ public void testBindingErrorWithFormatterAgainstList() { } @Test - public void testBindingWithFormatterAgainstFields() { + void testBindingWithFormatterAgainstFields() { TestBean tb = new TestBean(); DataBinder binder = new DataBinder(tb); FormattingConversionService conversionService = new FormattingConversionService(); @@ -506,18 +506,18 @@ public void testBindingWithFormatterAgainstFields() { LocaleContextHolder.setLocale(Locale.GERMAN); try { binder.bind(pvs); - assertThat(tb.getMyFloat()).isEqualTo(new Float(1.2)); + assertThat(tb.getMyFloat()).isEqualTo(Float.valueOf(1.2f)); assertThat(binder.getBindingResult().getFieldValue("myFloat")).isEqualTo("1,2"); PropertyEditor editor = binder.getBindingResult().findEditor("myFloat", Float.class); assertThat(editor).isNotNull(); - editor.setValue(new Float(1.4)); + editor.setValue(1.4f); assertThat(editor.getAsText()).isEqualTo("1,4"); editor = binder.getBindingResult().findEditor("myFloat", null); assertThat(editor).isNotNull(); editor.setAsText("1,6"); - assertThat(editor.getValue()).isEqualTo(new Float(1.6)); + assertThat(editor.getValue()).isEqualTo(1.6f); } finally { LocaleContextHolder.resetLocaleContext(); @@ -525,7 +525,7 @@ public void testBindingWithFormatterAgainstFields() { } @Test - public void testBindingErrorWithFormatterAgainstFields() { + void testBindingErrorWithFormatterAgainstFields() { TestBean tb = new TestBean(); DataBinder binder = new DataBinder(tb); binder.initDirectFieldAccess(); @@ -539,7 +539,7 @@ public void testBindingErrorWithFormatterAgainstFields() { LocaleContextHolder.setLocale(Locale.GERMAN); try { binder.bind(pvs); - assertThat(tb.getMyFloat()).isEqualTo(new Float(0.0)); + assertThat(tb.getMyFloat()).isEqualTo(Float.valueOf(0.0f)); assertThat(binder.getBindingResult().getFieldValue("myFloat")).isEqualTo("1x2"); assertThat(binder.getBindingResult().hasFieldErrors("myFloat")).isTrue(); } @@ -549,7 +549,7 @@ public void testBindingErrorWithFormatterAgainstFields() { } @Test - public void testBindingWithCustomFormatter() { + void testBindingWithCustomFormatter() { TestBean tb = new TestBean(); DataBinder binder = new DataBinder(tb); binder.addCustomFormatter(new NumberStyleFormatter(), Float.class); @@ -559,12 +559,12 @@ public void testBindingWithCustomFormatter() { LocaleContextHolder.setLocale(Locale.GERMAN); try { binder.bind(pvs); - assertThat(tb.getMyFloat()).isEqualTo(new Float(1.2)); + assertThat(tb.getMyFloat()).isEqualTo(Float.valueOf(1.2f)); assertThat(binder.getBindingResult().getFieldValue("myFloat")).isEqualTo("1,2"); PropertyEditor editor = binder.getBindingResult().findEditor("myFloat", Float.class); assertThat(editor).isNotNull(); - editor.setValue(new Float(1.4)); + editor.setValue(1.4f); assertThat(editor.getAsText()).isEqualTo("1,4"); editor = binder.getBindingResult().findEditor("myFloat", null); @@ -578,7 +578,7 @@ public void testBindingWithCustomFormatter() { } @Test - public void testBindingErrorWithCustomFormatter() { + void testBindingErrorWithCustomFormatter() { TestBean tb = new TestBean(); DataBinder binder = new DataBinder(tb); binder.addCustomFormatter(new NumberStyleFormatter()); @@ -588,7 +588,7 @@ public void testBindingErrorWithCustomFormatter() { LocaleContextHolder.setLocale(Locale.GERMAN); try { binder.bind(pvs); - assertThat(tb.getMyFloat()).isEqualTo(new Float(0.0)); + assertThat(tb.getMyFloat()).isEqualTo(Float.valueOf(0.0f)); assertThat(binder.getBindingResult().getFieldValue("myFloat")).isEqualTo("1x2"); assertThat(binder.getBindingResult().hasFieldErrors("myFloat")).isTrue(); assertThat(binder.getBindingResult().getFieldError("myFloat").getCode()).isEqualTo("typeMismatch"); @@ -599,7 +599,7 @@ public void testBindingErrorWithCustomFormatter() { } @Test - public void testBindingErrorWithParseExceptionFromCustomFormatter() { + void testBindingErrorWithParseExceptionFromCustomFormatter() { TestBean tb = new TestBean(); DataBinder binder = new DataBinder(tb); @@ -624,7 +624,7 @@ public String print(String object, Locale locale) { } @Test - public void testBindingErrorWithRuntimeExceptionFromCustomFormatter() { + void testBindingErrorWithRuntimeExceptionFromCustomFormatter() { TestBean tb = new TestBean(); DataBinder binder = new DataBinder(tb); @@ -649,7 +649,7 @@ public String print(String object, Locale locale) { } @Test - public void testConversionWithInappropriateStringEditor() { + void testConversionWithInappropriateStringEditor() { DataBinder dataBinder = new DataBinder(null); DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService(); dataBinder.setConversionService(conversionService); @@ -662,7 +662,7 @@ public void testConversionWithInappropriateStringEditor() { } @Test - public void testBindingWithAllowedFields() throws BindException { + void testBindingWithAllowedFields() throws BindException { TestBean rod = new TestBean(); DataBinder binder = new DataBinder(rod); binder.setAllowedFields("name", "myparam"); @@ -677,7 +677,7 @@ public void testBindingWithAllowedFields() throws BindException { } @Test - public void testBindingWithDisallowedFields() throws BindException { + void testBindingWithDisallowedFields() throws BindException { TestBean rod = new TestBean(); DataBinder binder = new DataBinder(rod); binder.setDisallowedFields("age"); @@ -695,7 +695,7 @@ public void testBindingWithDisallowedFields() throws BindException { } @Test - public void testBindingWithAllowedAndDisallowedFields() throws BindException { + void testBindingWithAllowedAndDisallowedFields() throws BindException { TestBean rod = new TestBean(); DataBinder binder = new DataBinder(rod); binder.setAllowedFields("name", "myparam"); @@ -709,12 +709,12 @@ public void testBindingWithAllowedAndDisallowedFields() throws BindException { assertThat(rod.getName().equals("Rod")).as("changed name correctly").isTrue(); assertThat(rod.getAge() == 0).as("did not change age").isTrue(); String[] disallowedFields = binder.getBindingResult().getSuppressedFields(); - assertThat(disallowedFields.length).isEqualTo(1); + assertThat(disallowedFields).hasSize(1); assertThat(disallowedFields[0]).isEqualTo("age"); } @Test - public void testBindingWithOverlappingAllowedAndDisallowedFields() throws BindException { + void testBindingWithOverlappingAllowedAndDisallowedFields() throws BindException { TestBean rod = new TestBean(); DataBinder binder = new DataBinder(rod); binder.setAllowedFields("name", "age"); @@ -728,12 +728,12 @@ public void testBindingWithOverlappingAllowedAndDisallowedFields() throws BindEx assertThat(rod.getName().equals("Rod")).as("changed name correctly").isTrue(); assertThat(rod.getAge() == 0).as("did not change age").isTrue(); String[] disallowedFields = binder.getBindingResult().getSuppressedFields(); - assertThat(disallowedFields.length).isEqualTo(1); + assertThat(disallowedFields).hasSize(1); assertThat(disallowedFields[0]).isEqualTo("age"); } @Test - public void testBindingWithAllowedFieldsUsingAsterisks() throws BindException { + void testBindingWithAllowedFieldsUsingAsterisks() throws BindException { TestBean rod = new TestBean(); DataBinder binder = new DataBinder(rod, "person"); binder.setAllowedFields("nam*", "*ouchy"); @@ -750,7 +750,7 @@ public void testBindingWithAllowedFieldsUsingAsterisks() throws BindException { assertThat("Rod".equals(rod.getTouchy())).as("changed touchy correctly").isTrue(); assertThat(rod.getAge() == 0).as("did not change age").isTrue(); String[] disallowedFields = binder.getBindingResult().getSuppressedFields(); - assertThat(disallowedFields.length).isEqualTo(1); + assertThat(disallowedFields).hasSize(1); assertThat(disallowedFields[0]).isEqualTo("age"); Map m = binder.getBindingResult().getModel(); @@ -760,7 +760,7 @@ public void testBindingWithAllowedFieldsUsingAsterisks() throws BindException { } @Test - public void testBindingWithAllowedAndDisallowedMapFields() throws BindException { + void testBindingWithAllowedAndDisallowedMapFields() throws BindException { TestBean rod = new TestBean(); DataBinder binder = new DataBinder(rod); binder.setAllowedFields("someMap[key1]", "someMap[key2]"); @@ -779,7 +779,7 @@ public void testBindingWithAllowedAndDisallowedMapFields() throws BindException assertThat(rod.getSomeMap().get("key3")).isNull(); assertThat(rod.getSomeMap().get("key4")).isNull(); String[] disallowedFields = binder.getBindingResult().getSuppressedFields(); - assertThat(disallowedFields.length).isEqualTo(2); + assertThat(disallowedFields).hasSize(2); assertThat(ObjectUtils.containsElement(disallowedFields, "someMap[key3]")).isTrue(); assertThat(ObjectUtils.containsElement(disallowedFields, "someMap[key4]")).isTrue(); } @@ -788,7 +788,7 @@ public void testBindingWithAllowedAndDisallowedMapFields() throws BindException * Tests for required field, both null, non-existing and empty strings. */ @Test - public void testBindingWithRequiredFields() { + void testBindingWithRequiredFields() { TestBean tb = new TestBean(); tb.setSpouse(new TestBean()); @@ -819,7 +819,7 @@ public void testBindingWithRequiredFields() { } @Test - public void testBindingWithRequiredMapFields() { + void testBindingWithRequiredMapFields() { TestBean tb = new TestBean(); tb.setSpouse(new TestBean()); @@ -839,7 +839,7 @@ public void testBindingWithRequiredMapFields() { } @Test - public void testBindingWithNestedObjectCreation() { + void testBindingWithNestedObjectCreation() { TestBean tb = new TestBean(); DataBinder binder = new DataBinder(tb, "person"); @@ -860,7 +860,7 @@ public void setAsText(String text) throws IllegalArgumentException { } @Test - public void testCustomEditorWithOldValueAccess() { + void testCustomEditorWithOldValueAccess() { TestBean tb = new TestBean(); DataBinder binder = new DataBinder(tb, "tb"); @@ -885,7 +885,7 @@ public void setAsText(String text) throws IllegalArgumentException { } @Test - public void testCustomEditorForSingleProperty() { + void testCustomEditorForSingleProperty() { TestBean tb = new TestBean(); tb.setSpouse(new TestBean()); DataBinder binder = new DataBinder(tb, "tb"); @@ -925,7 +925,7 @@ public String getAsText() { } @Test - public void testCustomEditorForPrimitiveProperty() { + void testCustomEditorForPrimitiveProperty() { TestBean tb = new TestBean(); DataBinder binder = new DataBinder(tb, "tb"); @@ -949,7 +949,7 @@ public String getAsText() { } @Test - public void testCustomEditorForAllStringProperties() { + void testCustomEditorForAllStringProperties() { TestBean tb = new TestBean(); DataBinder binder = new DataBinder(tb, "tb"); @@ -981,7 +981,7 @@ public String getAsText() { } @Test - public void testCustomFormatterForSingleProperty() { + void testCustomFormatterForSingleProperty() { TestBean tb = new TestBean(); tb.setSpouse(new TestBean()); DataBinder binder = new DataBinder(tb, "tb"); @@ -1021,7 +1021,7 @@ public String print(String object, Locale locale) { } @Test - public void testCustomFormatterForPrimitiveProperty() { + void testCustomFormatterForPrimitiveProperty() { TestBean tb = new TestBean(); DataBinder binder = new DataBinder(tb, "tb"); @@ -1045,7 +1045,7 @@ public String print(Integer object, Locale locale) { } @Test - public void testCustomFormatterForAllStringProperties() { + void testCustomFormatterForAllStringProperties() { TestBean tb = new TestBean(); DataBinder binder = new DataBinder(tb, "tb"); @@ -1077,7 +1077,7 @@ public String print(String object, Locale locale) { } @Test - public void testJavaBeanPropertyConventions() { + void testJavaBeanPropertyConventions() { Book book = new Book(); DataBinder binder = new DataBinder(book); @@ -1101,7 +1101,7 @@ public void testJavaBeanPropertyConventions() { } @Test - public void testOptionalProperty() { + void testOptionalProperty() { OptionalHolder bean = new OptionalHolder(); DataBinder binder = new DataBinder(bean); binder.setConversionService(new DefaultConversionService()); @@ -1111,7 +1111,7 @@ public void testOptionalProperty() { pvs.add("name", null); binder.bind(pvs); assertThat(bean.getId()).isEqualTo("1"); - assertThat(bean.getName().isPresent()).isFalse(); + assertThat(bean.getName()).isEmpty(); pvs = new MutablePropertyValues(); pvs.add("id", "2"); @@ -1122,7 +1122,7 @@ public void testOptionalProperty() { } @Test - public void testValidatorNoErrors() throws Exception { + void testValidatorNoErrors() throws Exception { TestBean tb = new TestBean(); tb.setAge(33); tb.setName("Rod"); @@ -1183,7 +1183,7 @@ public void testValidatorNoErrors() throws Exception { } @Test - public void testValidatorWithErrors() { + void testValidatorWithErrors() { TestBean tb = new TestBean(); tb.setSpouse(new TestBean()); @@ -1252,7 +1252,7 @@ public void testValidatorWithErrors() { } @Test - public void testValidatorWithErrorsAndCodesPrefix() { + void testValidatorWithErrorsAndCodesPrefix() { TestBean tb = new TestBean(); tb.setSpouse(new TestBean()); @@ -1324,7 +1324,7 @@ public void testValidatorWithErrorsAndCodesPrefix() { } @Test - public void testValidatorWithNestedObjectNull() { + void testValidatorWithNestedObjectNull() { TestBean tb = new TestBean(); Errors errors = new BeanPropertyBindingResult(tb, "tb"); Validator testValidator = new TestBeanValidator(); @@ -1343,7 +1343,7 @@ public void testValidatorWithNestedObjectNull() { } @Test - public void testNestedValidatorWithoutNestedPath() { + void testNestedValidatorWithoutNestedPath() { TestBean tb = new TestBean(); tb.setName("XXX"); Errors errors = new BeanPropertyBindingResult(tb, "tb"); @@ -1357,13 +1357,13 @@ public void testNestedValidatorWithoutNestedPath() { } @Test - public void testBindingStringArrayToIntegerSet() { + void testBindingStringArrayToIntegerSet() { IndexedTestBean tb = new IndexedTestBean(); DataBinder binder = new DataBinder(tb, "tb"); binder.registerCustomEditor(Set.class, new CustomCollectionEditor(TreeSet.class) { @Override protected Object convertElement(Object element) { - return new Integer(element.toString()); + return Integer.valueOf(element.toString()); } }); MutablePropertyValues pvs = new MutablePropertyValues(); @@ -1386,7 +1386,7 @@ protected Object convertElement(Object element) { } @Test - public void testBindingNullToEmptyCollection() { + void testBindingNullToEmptyCollection() { IndexedTestBean tb = new IndexedTestBean(); DataBinder binder = new DataBinder(tb, "tb"); binder.registerCustomEditor(Set.class, new CustomCollectionEditor(TreeSet.class, true)); @@ -1400,7 +1400,7 @@ public void testBindingNullToEmptyCollection() { } @Test - public void testBindingToIndexedField() { + void testBindingToIndexedField() { IndexedTestBean tb = new IndexedTestBean(); DataBinder binder = new DataBinder(tb, "tb"); binder.registerCustomEditor(String.class, "array.name", new PropertyEditorSupport() { @@ -1439,7 +1439,7 @@ public void setAsText(String text) throws IllegalArgumentException { } @Test - public void testBindingToNestedIndexedField() { + void testBindingToNestedIndexedField() { IndexedTestBean tb = new IndexedTestBean(); tb.getArray()[0].setNestedIndexedBean(new IndexedTestBean()); tb.getArray()[1].setNestedIndexedBean(new IndexedTestBean()); @@ -1470,7 +1470,7 @@ public void setAsText(String text) throws IllegalArgumentException { } @Test - public void testEditorForNestedIndexedField() { + void testEditorForNestedIndexedField() { IndexedTestBean tb = new IndexedTestBean(); tb.getArray()[0].setNestedIndexedBean(new IndexedTestBean()); tb.getArray()[1].setNestedIndexedBean(new IndexedTestBean()); @@ -1496,7 +1496,7 @@ public String getAsText() { } @Test - public void testSpecificEditorForNestedIndexedField() { + void testSpecificEditorForNestedIndexedField() { IndexedTestBean tb = new IndexedTestBean(); tb.getArray()[0].setNestedIndexedBean(new IndexedTestBean()); tb.getArray()[1].setNestedIndexedBean(new IndexedTestBean()); @@ -1522,7 +1522,7 @@ public String getAsText() { } @Test - public void testInnerSpecificEditorForNestedIndexedField() { + void testInnerSpecificEditorForNestedIndexedField() { IndexedTestBean tb = new IndexedTestBean(); tb.getArray()[0].setNestedIndexedBean(new IndexedTestBean()); tb.getArray()[1].setNestedIndexedBean(new IndexedTestBean()); @@ -1548,7 +1548,7 @@ public String getAsText() { } @Test - public void testDirectBindingToIndexedField() { + void testDirectBindingToIndexedField() { IndexedTestBean tb = new IndexedTestBean(); DataBinder binder = new DataBinder(tb, "tb"); binder.registerCustomEditor(TestBean.class, "array", new PropertyEditorSupport() { @@ -1601,7 +1601,7 @@ public String getAsText() { } @Test - public void testDirectBindingToEmptyIndexedFieldWithRegisteredSpecificEditor() { + void testDirectBindingToEmptyIndexedFieldWithRegisteredSpecificEditor() { IndexedTestBean tb = new IndexedTestBean(); DataBinder binder = new DataBinder(tb, "tb"); binder.registerCustomEditor(TestBean.class, "map[key0]", new PropertyEditorSupport() { @@ -1632,7 +1632,7 @@ public String getAsText() { } @Test - public void testDirectBindingToEmptyIndexedFieldWithRegisteredGenericEditor() { + void testDirectBindingToEmptyIndexedFieldWithRegisteredGenericEditor() { IndexedTestBean tb = new IndexedTestBean(); DataBinder binder = new DataBinder(tb, "tb"); binder.registerCustomEditor(TestBean.class, "map", new PropertyEditorSupport() { @@ -1663,7 +1663,7 @@ public String getAsText() { } @Test - public void testCustomEditorWithSubclass() { + void testCustomEditorWithSubclass() { IndexedTestBean tb = new IndexedTestBean(); DataBinder binder = new DataBinder(tb, "tb"); binder.registerCustomEditor(TestBean.class, new PropertyEditorSupport() { @@ -1697,7 +1697,7 @@ public String getAsText() { } @Test - public void testBindToStringArrayWithArrayEditor() { + void testBindToStringArrayWithArrayEditor() { TestBean tb = new TestBean(); DataBinder binder = new DataBinder(tb, "tb"); binder.registerCustomEditor(String[].class, "stringArray", new PropertyEditorSupport() { @@ -1717,7 +1717,7 @@ public void setAsText(String text) throws IllegalArgumentException { } @Test - public void testBindToStringArrayWithComponentEditor() { + void testBindToStringArrayWithComponentEditor() { TestBean tb = new TestBean(); DataBinder binder = new DataBinder(tb, "tb"); binder.registerCustomEditor(String.class, "stringArray", new PropertyEditorSupport() { @@ -1737,7 +1737,7 @@ public void setAsText(String text) throws IllegalArgumentException { } @Test - public void testBindingErrors() { + void testBindingErrors() { TestBean rod = new TestBean(); DataBinder binder = new DataBinder(rod, "person"); MutablePropertyValues pvs = new MutablePropertyValues(); @@ -1764,7 +1764,7 @@ public void testBindingErrors() { } @Test - public void testAddAllErrors() { + void testAddAllErrors() { TestBean rod = new TestBean(); DataBinder binder = new DataBinder(rod, "person"); MutablePropertyValues pvs = new MutablePropertyValues(); @@ -1784,7 +1784,7 @@ public void testAddAllErrors() { @Test @SuppressWarnings("unchecked") - public void testBindingWithResortedList() { + void testBindingWithResortedList() { IndexedTestBean tb = new IndexedTestBean(); DataBinder binder = new DataBinder(tb, "tb"); MutablePropertyValues pvs = new MutablePropertyValues(); @@ -1802,7 +1802,7 @@ public void testBindingWithResortedList() { } @Test - public void testRejectWithoutDefaultMessage() { + void testRejectWithoutDefaultMessage() { TestBean tb = new TestBean(); tb.setName("myName"); tb.setAge(99); @@ -1820,7 +1820,7 @@ public void testRejectWithoutDefaultMessage() { } @Test - public void testBindExceptionSerializable() throws Exception { + void testBindExceptionSerializable() throws Exception { SerializablePerson tb = new SerializablePerson(); tb.setName("myName"); tb.setAge(99); @@ -1849,7 +1849,7 @@ public void testBindExceptionSerializable() throws Exception { } @Test - public void testTrackDisallowedFields() { + void testTrackDisallowedFields() { TestBean testBean = new TestBean(); DataBinder binder = new DataBinder(testBean, "testBean"); binder.setAllowedFields("name", "age"); @@ -1864,12 +1864,12 @@ public void testTrackDisallowedFields() { assertThat(testBean.getName()).isEqualTo(name); String[] disallowedFields = binder.getBindingResult().getSuppressedFields(); - assertThat(disallowedFields.length).isEqualTo(1); + assertThat(disallowedFields).hasSize(1); assertThat(disallowedFields[0]).isEqualTo("beanName"); } @Test - public void testAutoGrowWithinDefaultLimit() { + void testAutoGrowWithinDefaultLimit() { TestBean testBean = new TestBean(); DataBinder binder = new DataBinder(testBean, "testBean"); @@ -1877,11 +1877,11 @@ public void testAutoGrowWithinDefaultLimit() { mpvs.add("friends[4]", ""); binder.bind(mpvs); - assertThat(testBean.getFriends().size()).isEqualTo(5); + assertThat(testBean.getFriends()).hasSize(5); } @Test - public void testAutoGrowBeyondDefaultLimit() { + void testAutoGrowBeyondDefaultLimit() { TestBean testBean = new TestBean(); DataBinder binder = new DataBinder(testBean, "testBean"); @@ -1894,7 +1894,7 @@ public void testAutoGrowBeyondDefaultLimit() { } @Test - public void testAutoGrowWithinCustomLimit() { + void testAutoGrowWithinCustomLimit() { TestBean testBean = new TestBean(); DataBinder binder = new DataBinder(testBean, "testBean"); binder.setAutoGrowCollectionLimit(10); @@ -1903,11 +1903,11 @@ public void testAutoGrowWithinCustomLimit() { mpvs.add("friends[4]", ""); binder.bind(mpvs); - assertThat(testBean.getFriends().size()).isEqualTo(5); + assertThat(testBean.getFriends()).hasSize(5); } @Test - public void testAutoGrowBeyondCustomLimit() { + void testAutoGrowBeyondCustomLimit() { TestBean testBean = new TestBean(); DataBinder binder = new DataBinder(testBean, "testBean"); binder.setAutoGrowCollectionLimit(10); @@ -1921,7 +1921,7 @@ public void testAutoGrowBeyondCustomLimit() { } @Test - public void testNestedGrowingList() { + void testNestedGrowingList() { Form form = new Form(); DataBinder binder = new DataBinder(form, "form"); MutablePropertyValues mpv = new MutablePropertyValues(); @@ -1937,7 +1937,7 @@ public void testNestedGrowingList() { } @Test - public void testFieldErrorAccessVariations() { + void testFieldErrorAccessVariations() { TestBean testBean = new TestBean(); DataBinder binder = new DataBinder(testBean, "testBean"); assertThat(binder.getBindingResult().getGlobalError()).isNull(); @@ -1958,7 +1958,7 @@ public void testFieldErrorAccessVariations() { } @Test // SPR-14888 - public void testSetAutoGrowCollectionLimit() { + void testSetAutoGrowCollectionLimit() { BeanWithIntegerList tb = new BeanWithIntegerList(); DataBinder binder = new DataBinder(tb); binder.setAutoGrowCollectionLimit(257); @@ -1968,11 +1968,11 @@ public void testSetAutoGrowCollectionLimit() { binder.bind(pvs); assertThat(tb.getIntegerList().size()).isEqualTo(257); assertThat(tb.getIntegerList().get(256)).isEqualTo(Integer.valueOf(1)); - assertThat(binder.getBindingResult().getFieldValue("integerList[256]")).isEqualTo(Integer.valueOf(1)); + assertThat(binder.getBindingResult().getFieldValue("integerList[256]")).isEqualTo(1); } @Test // SPR-14888 - public void testSetAutoGrowCollectionLimitAfterInitialization() { + void testSetAutoGrowCollectionLimitAfterInitialization() { DataBinder binder = new DataBinder(new BeanWithIntegerList()); binder.registerCustomEditor(String.class, new StringTrimmerEditor(true)); assertThatIllegalStateException().isThrownBy(() -> @@ -1981,7 +1981,7 @@ public void testSetAutoGrowCollectionLimitAfterInitialization() { } @Test // SPR-15009 - public void testSetCustomMessageCodesResolverBeforeInitializeBindingResultForBeanPropertyAccess() { + void testSetCustomMessageCodesResolverBeforeInitializeBindingResultForBeanPropertyAccess() { TestBean testBean = new TestBean(); DataBinder binder = new DataBinder(testBean, "testBean"); DefaultMessageCodesResolver messageCodesResolver = new DefaultMessageCodesResolver(); @@ -1998,7 +1998,7 @@ public void testSetCustomMessageCodesResolverBeforeInitializeBindingResultForBea } @Test // SPR-15009 - public void testSetCustomMessageCodesResolverBeforeInitializeBindingResultForDirectFieldAccess() { + void testSetCustomMessageCodesResolverBeforeInitializeBindingResultForDirectFieldAccess() { TestBean testBean = new TestBean(); DataBinder binder = new DataBinder(testBean, "testBean"); DefaultMessageCodesResolver messageCodesResolver = new DefaultMessageCodesResolver(); @@ -2013,7 +2013,7 @@ public void testSetCustomMessageCodesResolverBeforeInitializeBindingResultForDir } @Test // SPR-15009 - public void testSetCustomMessageCodesResolverAfterInitializeBindingResult() { + void testSetCustomMessageCodesResolverAfterInitializeBindingResult() { TestBean testBean = new TestBean(); DataBinder binder = new DataBinder(testBean, "testBean"); binder.initBeanPropertyAccess(); @@ -2028,7 +2028,7 @@ public void testSetCustomMessageCodesResolverAfterInitializeBindingResult() { } @Test // SPR-15009 - public void testSetMessageCodesResolverIsNullAfterInitializeBindingResult() { + void testSetMessageCodesResolverIsNullAfterInitializeBindingResult() { TestBean testBean = new TestBean(); DataBinder binder = new DataBinder(testBean, "testBean"); binder.initBeanPropertyAccess(); @@ -2042,7 +2042,7 @@ public void testSetMessageCodesResolverIsNullAfterInitializeBindingResult() { } @Test // SPR-15009 - public void testCallSetMessageCodesResolverTwice() { + void testCallSetMessageCodesResolverTwice() { TestBean testBean = new TestBean(); DataBinder binder = new DataBinder(testBean, "testBean"); @@ -2053,7 +2053,7 @@ public void testCallSetMessageCodesResolverTwice() { } @Test // gh-24347 - public void overrideBindingResultType() { + void overrideBindingResultType() { TestBean testBean = new TestBean(); DataBinder binder = new DataBinder(testBean, "testBean"); binder.initDirectFieldAccess(); diff --git a/spring-core/kotlin-coroutines/kotlin-coroutines.gradle b/spring-core/kotlin-coroutines/kotlin-coroutines.gradle deleted file mode 100644 index 24efbb4fea70..000000000000 --- a/spring-core/kotlin-coroutines/kotlin-coroutines.gradle +++ /dev/null @@ -1,35 +0,0 @@ -description = "Spring Core Coroutines support" - -apply plugin: "kotlin" - -configurations { - classesOnlyElements { - canBeConsumed = true - canBeResolved = false - } -} - -artifacts { - classesOnlyElements(compileKotlin.destinationDir) -} - -dependencies { - compile("org.jetbrains.kotlin:kotlin-reflect") - compile("org.jetbrains.kotlin:kotlin-stdlib") - compile("io.projectreactor:reactor-core") - compile("org.jetbrains.kotlinx:kotlinx-coroutines-core") - compile("org.jetbrains.kotlinx:kotlinx-coroutines-reactor") -} - -eclipse { - project { - buildCommand "org.jetbrains.kotlin.ui.kotlinBuilder" - buildCommand "org.eclipse.jdt.core.javabuilder" - natures "org.jetbrains.kotlin.core.kotlinNature" - natures "org.eclipse.jdt.core.javanature" - linkedResource name: "kotlin_bin", type: "2", locationUri: "org.jetbrains.kotlin.core.filesystem:/" + project.name + "/kotlin_bin" - } - classpath { - containers "org.jetbrains.kotlin.core.KOTLIN_CONTAINER" - } -} diff --git a/spring-core/kotlin-coroutines/src/main/kotlin/org/springframework/core/CoroutinesUtils.kt b/spring-core/kotlin-coroutines/src/main/kotlin/org/springframework/core/CoroutinesUtils.kt deleted file mode 100644 index 3d716bb685e0..000000000000 --- a/spring-core/kotlin-coroutines/src/main/kotlin/org/springframework/core/CoroutinesUtils.kt +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2002-2021 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. - */ - -@file:JvmName("CoroutinesUtils") -package org.springframework.core - -import kotlinx.coroutines.* -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.reactive.awaitSingleOrNull -import kotlinx.coroutines.reactor.asFlux - -import kotlinx.coroutines.reactor.mono -import org.reactivestreams.Publisher -import reactor.core.publisher.Mono -import java.lang.reflect.InvocationTargetException -import java.lang.reflect.Method -import kotlin.reflect.full.callSuspend -import kotlin.reflect.jvm.kotlinFunction - -/** - * Convert a [Deferred] instance to a [Mono] one. - * - * @author Sebastien Deleuze - * @since 5.2 - */ -internal fun deferredToMono(source: Deferred) = - mono(Dispatchers.Unconfined) { source.await() } - -/** - * Convert a [Mono] instance to a [Deferred] one. - * - * @author Sebastien Deleuze - * @since 5.2 - */ -@Suppress("DEPRECATION") -@OptIn(DelicateCoroutinesApi::class) -internal fun monoToDeferred(source: Mono) = - GlobalScope.async(Dispatchers.Unconfined) { source.awaitSingleOrNull() } - -/** - * Invoke a suspending function and converts it to [Mono] or [reactor.core.publisher.Flux]. - * - * @author Sebastien Deleuze - * @since 5.2 - */ -@Suppress("UNCHECKED_CAST") -fun invokeSuspendingFunction(method: Method, target: Any, vararg args: Any?): Publisher<*> { - val function = method.kotlinFunction!! - val mono = mono(Dispatchers.Unconfined) { - function.callSuspend(target, *args.sliceArray(0..(args.size-2))).let { if (it == Unit) null else it } - }.onErrorMap(InvocationTargetException::class.java) { it.targetException } - return if (function.returnType.classifier == Flow::class) { - mono.flatMapMany { (it as Flow).asFlux() } - } - else { - mono - } -} diff --git a/spring-core/spring-core.gradle b/spring-core/spring-core.gradle index a4166705d32d..a6e5e309b073 100644 --- a/spring-core/spring-core.gradle +++ b/spring-core/spring-core.gradle @@ -13,20 +13,19 @@ def objenesisVersion = "3.2" configurations { cglib objenesis - coroutines } task cglibRepackJar(type: ShadowJar) { - archiveBaseName = 'spring-cglib-repack' - archiveVersion = cglibVersion + archiveBaseName.set('spring-cglib-repack') + archiveVersion.set(cglibVersion) configurations = [project.configurations.cglib] relocate 'net.sf.cglib', 'org.springframework.cglib' relocate 'org.objectweb.asm', 'org.springframework.asm' } task objenesisRepackJar(type: ShadowJar) { - archiveBaseName = 'spring-objenesis-repack' - archiveVersion = objenesisVersion + archiveBaseName.set('spring-objenesis-repack') + archiveVersion.set(objenesisVersion) configurations = [project.configurations.objenesis] relocate 'org.objenesis', 'org.springframework.objenesis' } @@ -34,31 +33,31 @@ task objenesisRepackJar(type: ShadowJar) { dependencies { cglib("cglib:cglib:${cglibVersion}@jar") objenesis("org.objenesis:objenesis:${objenesisVersion}@jar") - coroutines(project(path: ":kotlin-coroutines", configuration: 'classesOnlyElements')) - compile(files(cglibRepackJar)) - compile(files(objenesisRepackJar)) - compile(project(":spring-jcl")) - compileOnly(project(":kotlin-coroutines")) + api(files(cglibRepackJar)) + api(files(objenesisRepackJar)) + api(project(":spring-jcl")) compileOnly("io.projectreactor.tools:blockhound") optional("net.sf.jopt-simple:jopt-simple") optional("org.aspectj:aspectjweaver") optional("org.jetbrains.kotlin:kotlin-reflect") optional("org.jetbrains.kotlin:kotlin-stdlib") + optional("org.jetbrains.kotlinx:kotlinx-coroutines-core") + optional("org.jetbrains.kotlinx:kotlinx-coroutines-reactor") optional("io.projectreactor:reactor-core") optional("io.reactivex:rxjava") optional("io.reactivex:rxjava-reactive-streams") optional("io.reactivex.rxjava2:rxjava") optional("io.reactivex.rxjava3:rxjava") + optional("io.smallrye.reactive:mutiny") optional("io.netty:netty-buffer") - testCompile("io.projectreactor:reactor-test") - testCompile("com.google.code.findbugs:jsr305") - testCompile("javax.annotation:javax.annotation-api") - testCompile("javax.xml.bind:jaxb-api") - testCompile("com.fasterxml.woodstox:woodstox-core") - testCompile("org.xmlunit:xmlunit-assertj") - testCompile("org.xmlunit:xmlunit-matchers") - testCompile(project(":kotlin-coroutines")) - testCompile("io.projectreactor.tools:blockhound") + testImplementation("io.projectreactor:reactor-test") + testImplementation("com.google.code.findbugs:jsr305") + testImplementation("javax.annotation:javax.annotation-api") + testImplementation("javax.xml.bind:jaxb-api") + testImplementation("com.fasterxml.woodstox:woodstox-core") + testImplementation("org.xmlunit:xmlunit-assertj") + testImplementation("org.xmlunit:xmlunit-matchers") + testImplementation("io.projectreactor.tools:blockhound") testFixturesImplementation("io.projectreactor:reactor-test") testFixturesImplementation("com.google.code.findbugs:jsr305") testFixturesImplementation("org.junit.platform:junit-platform-launcher") @@ -90,8 +89,6 @@ jar { from(zipTree(objenesisRepackJar.archivePath)) { include "org/springframework/objenesis/**" } - - from configurations.coroutines } test { diff --git a/spring-core/src/jmh/java/org/springframework/util/StringUtilsBenchmark.java b/spring-core/src/jmh/java/org/springframework/util/StringUtilsBenchmark.java new file mode 100644 index 000000000000..1fc7753b2218 --- /dev/null +++ b/spring-core/src/jmh/java/org/springframework/util/StringUtilsBenchmark.java @@ -0,0 +1,116 @@ +/* + * Copyright 2002-2021 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 org.springframework.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Random; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; + +/** + * Benchmarks for {@link StringUtils}. + * + * @author Brian Clozel + */ +@BenchmarkMode(Mode.Throughput) +public class StringUtilsBenchmark { + + @Benchmark + public void collectionToDelimitedString(DelimitedStringState state, Blackhole bh) { + bh.consume(StringUtils.collectionToCommaDelimitedString(state.elements)); + } + + @State(Scope.Benchmark) + public static class DelimitedStringState { + + @Param("10") + int elementMinSize; + + @Param("20") + int elementMaxSize; + + @Param("10") + int elementCount; + + Collection elements; + + @Setup(Level.Iteration) + public void setup() { + Random random = new Random(); + this.elements = new ArrayList<>(this.elementCount); + int bound = this.elementMaxSize - this.elementMinSize; + for (int i = 0; i < this.elementCount; i++) { + this.elements.add(String.format("%0" + (random.nextInt(bound) + this.elementMinSize) + "d", 1)); + } + } + } + + @Benchmark + public void cleanPath(CleanPathState state, Blackhole bh) { + for (String path : state.paths) { + bh.consume(StringUtils.cleanPath(path)); + } + } + + @State(Scope.Benchmark) + public static class CleanPathState { + + private static final List SEGMENTS = Arrays.asList("some", "path", ".", "..", "springspring"); + + @Param("10") + int segmentCount; + + @Param("20") + int pathsCount; + + Collection paths; + + @Setup(Level.Iteration) + public void setup() { + this.paths = new ArrayList<>(this.pathsCount); + Random random = new Random(); + for (int i = 0; i < this.pathsCount; i++) { + this.paths.add(createSamplePath(random)); + } + } + + private String createSamplePath(Random random) { + String separator = random.nextBoolean() ? "/" : "\\"; + StringBuilder sb = new StringBuilder(); + sb.append("jar:file:///c:"); + for (int i = 0; i < this.segmentCount; i++) { + sb.append(separator); + sb.append(SEGMENTS.get(random.nextInt(SEGMENTS.size()))); + } + sb.append(separator); + sb.append("the%20file.txt"); + return sb.toString(); + } + + } +} diff --git a/spring-core/src/main/java/org/springframework/asm/AnnotationVisitor.java b/spring-core/src/main/java/org/springframework/asm/AnnotationVisitor.java index 51357068800b..c3c236aefabb 100644 --- a/spring-core/src/main/java/org/springframework/asm/AnnotationVisitor.java +++ b/spring-core/src/main/java/org/springframework/asm/AnnotationVisitor.java @@ -38,8 +38,8 @@ public abstract class AnnotationVisitor { /** - * The ASM API version implemented by this visitor. The value of this field must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}. + * The ASM API version implemented by this visitor. The value of this field must be one of the + * {@code ASM}x values in {@link Opcodes}. */ protected final int api; @@ -52,8 +52,8 @@ public abstract class AnnotationVisitor { /** * Constructs a new {@link AnnotationVisitor}. * - * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}. + * @param api the ASM API version implemented by this visitor. Must be one of the {@code + * ASM}x values in {@link Opcodes}. */ public AnnotationVisitor(final int api) { this(api, null); @@ -62,8 +62,8 @@ public AnnotationVisitor(final int api) { /** * Constructs a new {@link AnnotationVisitor}. * - * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}. + * @param api the ASM API version implemented by this visitor. Must be one of the {@code + * ASM}x values in {@link Opcodes}. * @param annotationVisitor the annotation visitor to which this visitor must delegate method * calls. May be {@literal null}. */ diff --git a/spring-core/src/main/java/org/springframework/asm/ByteVector.java b/spring-core/src/main/java/org/springframework/asm/ByteVector.java index 3789eec3fd6d..6187c1e22c7d 100644 --- a/spring-core/src/main/java/org/springframework/asm/ByteVector.java +++ b/spring-core/src/main/java/org/springframework/asm/ByteVector.java @@ -352,6 +352,9 @@ public ByteVector putByteArray( * @param size number of additional bytes that this byte vector should be able to receive. */ private void enlarge(final int size) { + if (length > data.length) { + throw new AssertionError("Internal error"); + } int doubleCapacity = 2 * data.length; int minimalCapacity = length + size; byte[] newData = new byte[doubleCapacity > minimalCapacity ? doubleCapacity : minimalCapacity]; diff --git a/spring-core/src/main/java/org/springframework/asm/ClassVisitor.java b/spring-core/src/main/java/org/springframework/asm/ClassVisitor.java index b49c3eebce5e..05b448321afc 100644 --- a/spring-core/src/main/java/org/springframework/asm/ClassVisitor.java +++ b/spring-core/src/main/java/org/springframework/asm/ClassVisitor.java @@ -40,8 +40,8 @@ public abstract class ClassVisitor { /** - * The ASM API version implemented by this visitor. The value of this field must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}. + * The ASM API version implemented by this visitor. The value of this field must be one of the + * {@code ASM}x values in {@link Opcodes}. */ protected final int api; @@ -51,8 +51,8 @@ public abstract class ClassVisitor { /** * Constructs a new {@link ClassVisitor}. * - * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}. + * @param api the ASM API version implemented by this visitor. Must be one of the {@code + * ASM}x values in {@link Opcodes}. */ public ClassVisitor(final int api) { this(api, null); @@ -61,9 +61,8 @@ public ClassVisitor(final int api) { /** * Constructs a new {@link ClassVisitor}. * - * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link - * Opcodes#ASM8} or {@link Opcodes#ASM9}. + * @param api the ASM API version implemented by this visitor. Must be one of the {@code + * ASM}x values in {@link Opcodes}. * @param classVisitor the class visitor to which this visitor must delegate method calls. May be * null. */ diff --git a/spring-core/src/main/java/org/springframework/asm/FieldVisitor.java b/spring-core/src/main/java/org/springframework/asm/FieldVisitor.java index 841b4a3cb78f..727417045faa 100644 --- a/spring-core/src/main/java/org/springframework/asm/FieldVisitor.java +++ b/spring-core/src/main/java/org/springframework/asm/FieldVisitor.java @@ -37,9 +37,8 @@ public abstract class FieldVisitor { /** - * The ASM API version implemented by this visitor. The value of this field must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link - * Opcodes#ASM8} or {@link Opcodes#ASM9}. + * The ASM API version implemented by this visitor. The value of this field must be one of the + * {@code ASM}x values in {@link Opcodes}. */ protected final int api; @@ -49,9 +48,8 @@ public abstract class FieldVisitor { /** * Constructs a new {@link FieldVisitor}. * - * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7}, {@link - * Opcodes#ASM8} or {@link Opcodes#ASM9}. + * @param api the ASM API version implemented by this visitor. Must be one of the {@code + * ASM}x values in {@link Opcodes}. */ public FieldVisitor(final int api) { this(api, null); @@ -60,9 +58,8 @@ public FieldVisitor(final int api) { /** * Constructs a new {@link FieldVisitor}. * - * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6}, {@link Opcodes#ASM7} or {@link - * Opcodes#ASM8}. + * @param api the ASM API version implemented by this visitor. Must be one of the {@code + * ASM}x values in {@link Opcodes}. * @param fieldVisitor the field visitor to which this visitor must delegate method calls. May be * null. */ diff --git a/spring-core/src/main/java/org/springframework/asm/MethodVisitor.java b/spring-core/src/main/java/org/springframework/asm/MethodVisitor.java index ff5ce1056d27..15ca4a5e4eb3 100644 --- a/spring-core/src/main/java/org/springframework/asm/MethodVisitor.java +++ b/spring-core/src/main/java/org/springframework/asm/MethodVisitor.java @@ -51,8 +51,8 @@ public abstract class MethodVisitor { private static final String REQUIRES_ASM5 = "This feature requires ASM5"; /** - * The ASM API version implemented by this visitor. The value of this field must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}. + * The ASM API version implemented by this visitor. The value of this field must be one of the + * {@code ASM}x values in {@link Opcodes}. */ protected final int api; @@ -64,8 +64,8 @@ public abstract class MethodVisitor { /** * Constructs a new {@link MethodVisitor}. * - * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}. + * @param api the ASM API version implemented by this visitor. Must be one of the {@code + * ASM}x values in {@link Opcodes}. */ public MethodVisitor(final int api) { this(api, null); @@ -74,8 +74,8 @@ public MethodVisitor(final int api) { /** * Constructs a new {@link MethodVisitor}. * - * @param api the ASM API version implemented by this visitor. Must be one of {@link - * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}. + * @param api the ASM API version implemented by this visitor. Must be one of the {@code + * ASM}x values in {@link Opcodes}. * @param methodVisitor the method visitor to which this visitor must delegate method calls. May * be null. */ diff --git a/spring-core/src/main/java/org/springframework/core/CoroutinesUtils.java b/spring-core/src/main/java/org/springframework/core/CoroutinesUtils.java new file mode 100644 index 000000000000..50aec2deb3a6 --- /dev/null +++ b/spring-core/src/main/java/org/springframework/core/CoroutinesUtils.java @@ -0,0 +1,95 @@ +/* + * Copyright 2002-2021 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 org.springframework.core; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Objects; + +import kotlin.Unit; +import kotlin.jvm.JvmClassMappingKt; +import kotlin.reflect.KClassifier; +import kotlin.reflect.KFunction; +import kotlin.reflect.full.KCallables; +import kotlin.reflect.jvm.ReflectJvmMapping; +import kotlinx.coroutines.BuildersKt; +import kotlinx.coroutines.CoroutineStart; +import kotlinx.coroutines.Deferred; +import kotlinx.coroutines.Dispatchers; +import kotlinx.coroutines.GlobalScope; +import kotlinx.coroutines.flow.Flow; +import kotlinx.coroutines.reactor.MonoKt; +import kotlinx.coroutines.reactor.ReactorFlowKt; +import org.reactivestreams.Publisher; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +/** + * Utilities for working with Kotlin Coroutines. + * + * @author Sebastien Deleuze + * @author Phillip Webb + * @since 5.2 + */ +public abstract class CoroutinesUtils { + + /** + * Convert a {@link Deferred} instance to a {@link Mono}. + */ + public static Mono deferredToMono(Deferred source) { + return MonoKt.mono(Dispatchers.getUnconfined(), + (scope, continuation) -> source.await(continuation)); + } + + /** + * Convert a {@link Mono} instance to a {@link Deferred}. + */ + public static Deferred monoToDeferred(Mono source) { + return BuildersKt.async(GlobalScope.INSTANCE, Dispatchers.getUnconfined(), + CoroutineStart.DEFAULT, + (scope, continuation) -> MonoKt.awaitSingleOrNull(source, continuation)); + } + + /** + * Invoke a suspending function and converts it to {@link Mono} or + * {@link Flux}. + */ + public static Publisher invokeSuspendingFunction(Method method, Object target, Object... args) { + KFunction function = Objects.requireNonNull(ReflectJvmMapping.getKotlinFunction(method)); + KClassifier classifier = function.getReturnType().getClassifier(); + Mono mono = MonoKt.mono(Dispatchers.getUnconfined(), (scope, continuation) -> + KCallables.callSuspend(function, getSuspendedFunctionArgs(target, args), continuation)) + .filter(result -> !Objects.equals(result, Unit.INSTANCE)) + .onErrorMap(InvocationTargetException.class, InvocationTargetException::getTargetException); + if (classifier != null && classifier.equals(JvmClassMappingKt.getKotlinClass(Flow.class))) { + return mono.flatMapMany(CoroutinesUtils::asFlux); + } + return mono; + } + + private static Object[] getSuspendedFunctionArgs(Object target, Object... args) { + Object[] functionArgs = new Object[args.length]; + functionArgs[0] = target; + System.arraycopy(args, 0, functionArgs, 1, args.length - 1); + return functionArgs; + } + + private static Flux asFlux(Object flow) { + return ReactorFlowKt.asFlux(((Flow) flow)); + } + +} diff --git a/spring-core/src/main/java/org/springframework/core/ReactiveAdapterRegistry.java b/spring-core/src/main/java/org/springframework/core/ReactiveAdapterRegistry.java index a5a8b9295092..cfeaffcaf734 100644 --- a/spring-core/src/main/java/org/springframework/core/ReactiveAdapterRegistry.java +++ b/spring-core/src/main/java/org/springframework/core/ReactiveAdapterRegistry.java @@ -72,6 +72,8 @@ public class ReactiveAdapterRegistry { private static final boolean kotlinCoroutinesPresent; + private static final boolean mutinyPresent; + static { ClassLoader classLoader = ReactiveAdapterRegistry.class.getClassLoader(); reactorPresent = ClassUtils.isPresent("reactor.core.publisher.Flux", classLoader); @@ -81,6 +83,7 @@ public class ReactiveAdapterRegistry { rxjava3Present = ClassUtils.isPresent("io.reactivex.rxjava3.core.Flowable", classLoader); flowPublisherPresent = ClassUtils.isPresent("java.util.concurrent.Flow.Publisher", classLoader); kotlinCoroutinesPresent = ClassUtils.isPresent("kotlinx.coroutines.reactor.MonoKt", classLoader); + mutinyPresent = ClassUtils.isPresent("io.smallrye.mutiny.Multi", classLoader); } private final List adapters = new ArrayList<>(); @@ -121,6 +124,11 @@ public ReactiveAdapterRegistry() { if (reactorPresent && kotlinCoroutinesPresent) { new CoroutinesRegistrar().registerAdapters(this); } + + // SmallRye Mutiny + if (mutinyPresent) { + new MutinyRegistrar().registerAdapters(this); + } } @@ -418,6 +426,28 @@ void registerAdapters(ReactiveAdapterRegistry registry) { } + private static class MutinyRegistrar { + + void registerAdapters(ReactiveAdapterRegistry registry) { + registry.registerReactiveType( + ReactiveTypeDescriptor.singleOptionalValue( + io.smallrye.mutiny.Uni.class, + () -> io.smallrye.mutiny.Uni.createFrom().nothing()), + uni -> ((io.smallrye.mutiny.Uni) uni).convert().toPublisher(), + publisher -> io.smallrye.mutiny.Uni.createFrom().publisher(publisher) + ); + + registry.registerReactiveType( + ReactiveTypeDescriptor.multiValue( + io.smallrye.mutiny.Multi.class, + () -> io.smallrye.mutiny.Multi.createFrom().empty()), + multi -> (io.smallrye.mutiny.Multi) multi, + publisher -> io.smallrye.mutiny.Multi.createFrom().publisher(publisher) + ); + } + } + + /** * {@code BlockHoundIntegration} for spring-core classes. *

Explicitly allow the following: diff --git a/spring-core/src/main/java/org/springframework/util/ConcurrentLruCache.java b/spring-core/src/main/java/org/springframework/util/ConcurrentLruCache.java index 2f1f2e08965d..1d99b4cd093f 100644 --- a/spring-core/src/main/java/org/springframework/util/ConcurrentLruCache.java +++ b/spring-core/src/main/java/org/springframework/util/ConcurrentLruCache.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -174,7 +174,7 @@ public int size() { } /** - * Return the the maximum number of entries in the cache + * Return the maximum number of entries in the cache * (0 indicates no caching, always generating a new value). * @see #size() */ diff --git a/spring-core/src/main/java/org/springframework/util/ObjectUtils.java b/spring-core/src/main/java/org/springframework/util/ObjectUtils.java index 8089a1313e7b..f5a703c30181 100644 --- a/spring-core/src/main/java/org/springframework/util/ObjectUtils.java +++ b/spring-core/src/main/java/org/springframework/util/ObjectUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -114,7 +114,7 @@ public static boolean isEmpty(@Nullable Object[] array) { * Determine whether the given object is empty. *

This method supports the following object types. *

    - *
  • {@code Optional}: considered empty if {@link Optional#empty()}
  • + *
  • {@code Optional}: considered empty if not {@link Optional#isPresent()}
  • *
  • {@code Array}: considered empty if its length is zero
  • *
  • {@link CharSequence}: considered empty if its length is zero
  • *
  • {@link Collection}: delegates to {@link Collection#isEmpty()}
  • diff --git a/spring-core/src/main/java/org/springframework/util/StringUtils.java b/spring-core/src/main/java/org/springframework/util/StringUtils.java index edbbaea91d45..80a996d481fb 100644 --- a/spring-core/src/main/java/org/springframework/util/StringUtils.java +++ b/spring-core/src/main/java/org/springframework/util/StringUtils.java @@ -667,7 +667,9 @@ public static String cleanPath(String path) { if (!hasLength(path)) { return path; } - String pathToUse = replace(path, WINDOWS_FOLDER_SEPARATOR, FOLDER_SEPARATOR); + + String normalizedPath = replace(path, WINDOWS_FOLDER_SEPARATOR, FOLDER_SEPARATOR); + String pathToUse = normalizedPath; // Shortcut if there is no work to do if (pathToUse.indexOf('.') == -1) { @@ -695,7 +697,8 @@ public static String cleanPath(String path) { } String[] pathArray = delimitedListToStringArray(pathToUse, FOLDER_SEPARATOR); - Deque pathElements = new ArrayDeque<>(); + // we never require more elements than pathArray and in the common case the same number + Deque pathElements = new ArrayDeque<>(pathArray.length); int tops = 0; for (int i = pathArray.length - 1; i >= 0; i--) { @@ -721,7 +724,7 @@ else if (TOP_PATH.equals(element)) { // All path elements stayed the same - shortcut if (pathArray.length == pathElements.size()) { - return prefix + pathToUse; + return normalizedPath; } // Remaining top paths need to be retained. for (int i = 0; i < tops; i++) { @@ -732,7 +735,9 @@ else if (TOP_PATH.equals(element)) { pathElements.addFirst(CURRENT_PATH); } - return prefix + collectionToDelimitedString(pathElements, FOLDER_SEPARATOR); + final String joined = collectionToDelimitedString(pathElements, FOLDER_SEPARATOR); + // avoid string concatenation with empty prefix + return prefix.isEmpty() ? joined : prefix + joined; } /** @@ -1294,7 +1299,12 @@ public static String collectionToDelimitedString( return ""; } - StringBuilder sb = new StringBuilder(); + int totalLength = coll.size() * (prefix.length() + suffix.length()) + (coll.size() - 1) * delim.length(); + for (Object element : coll) { + totalLength += element.toString().length(); + } + + StringBuilder sb = new StringBuilder(totalLength); Iterator it = coll.iterator(); while (it.hasNext()) { sb.append(prefix).append(it.next()).append(suffix); diff --git a/spring-core/src/test/java/org/springframework/core/ReactiveAdapterRegistryTests.java b/spring-core/src/test/java/org/springframework/core/ReactiveAdapterRegistryTests.java index 4dc08a704f29..579e1a463afc 100644 --- a/spring-core/src/test/java/org/springframework/core/ReactiveAdapterRegistryTests.java +++ b/spring-core/src/test/java/org/springframework/core/ReactiveAdapterRegistryTests.java @@ -21,6 +21,8 @@ import java.util.List; import java.util.concurrent.CompletableFuture; +import io.smallrye.mutiny.Multi; +import io.smallrye.mutiny.Uni; import kotlinx.coroutines.Deferred; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -38,6 +40,9 @@ @SuppressWarnings("unchecked") class ReactiveAdapterRegistryTests { + private static final Duration ONE_SECOND = Duration.ofSeconds(1); + + private final ReactiveAdapterRegistry registry = ReactiveAdapterRegistry.getSharedInstance(); @@ -83,7 +88,7 @@ void toFlux() { Publisher source = io.reactivex.rxjava3.core.Flowable.fromIterable(sequence); Object target = getAdapter(Flux.class).fromPublisher(source); assertThat(target instanceof Flux).isTrue(); - assertThat(((Flux) target).collectList().block(Duration.ofMillis(1000))).isEqualTo(sequence); + assertThat(((Flux) target).collectList().block(ONE_SECOND)).isEqualTo(sequence); } @Test @@ -91,7 +96,7 @@ void toMono() { Publisher source = io.reactivex.rxjava3.core.Flowable.fromArray(1, 2, 3); Object target = getAdapter(Mono.class).fromPublisher(source); assertThat(target instanceof Mono).isTrue(); - assertThat(((Mono) target).block(Duration.ofMillis(1000))).isEqualTo(Integer.valueOf(1)); + assertThat(((Mono) target).block(ONE_SECOND)).isEqualTo(Integer.valueOf(1)); } @Test @@ -108,7 +113,7 @@ void fromCompletableFuture() { future.complete(1); Object target = getAdapter(CompletableFuture.class).toPublisher(future); assertThat(target instanceof Mono).as("Expected Mono Publisher: " + target.getClass().getName()).isTrue(); - assertThat(((Mono) target).block(Duration.ofMillis(1000))).isEqualTo(Integer.valueOf(1)); + assertThat(((Mono) target).block(ONE_SECOND)).isEqualTo(Integer.valueOf(1)); } } @@ -153,7 +158,7 @@ void fromObservable() { Object source = rx.Observable.from(sequence); Object target = getAdapter(rx.Observable.class).toPublisher(source); assertThat(target instanceof Flux).as("Expected Flux Publisher: " + target.getClass().getName()).isTrue(); - assertThat(((Flux) target).collectList().block(Duration.ofMillis(1000))).isEqualTo(sequence); + assertThat(((Flux) target).collectList().block(ONE_SECOND)).isEqualTo(sequence); } @Test @@ -161,7 +166,7 @@ void fromSingle() { Object source = rx.Single.just(1); Object target = getAdapter(rx.Single.class).toPublisher(source); assertThat(target instanceof Mono).as("Expected Mono Publisher: " + target.getClass().getName()).isTrue(); - assertThat(((Mono) target).block(Duration.ofMillis(1000))).isEqualTo(Integer.valueOf(1)); + assertThat(((Mono) target).block(ONE_SECOND)).isEqualTo(Integer.valueOf(1)); } @Test @@ -169,7 +174,7 @@ void fromCompletable() { Object source = rx.Completable.complete(); Object target = getAdapter(rx.Completable.class).toPublisher(source); assertThat(target instanceof Mono).as("Expected Mono Publisher: " + target.getClass().getName()).isTrue(); - ((Mono) target).block(Duration.ofMillis(1000)); + ((Mono) target).block(ONE_SECOND); } } @@ -227,7 +232,7 @@ void fromFlowable() { Object source = io.reactivex.Flowable.fromIterable(sequence); Object target = getAdapter(io.reactivex.Flowable.class).toPublisher(source); assertThat(target instanceof Flux).as("Expected Flux Publisher: " + target.getClass().getName()).isTrue(); - assertThat(((Flux) target).collectList().block(Duration.ofMillis(1000))).isEqualTo(sequence); + assertThat(((Flux) target).collectList().block(ONE_SECOND)).isEqualTo(sequence); } @Test @@ -236,7 +241,7 @@ void fromObservable() { Object source = io.reactivex.Observable.fromIterable(sequence); Object target = getAdapter(io.reactivex.Observable.class).toPublisher(source); assertThat(target instanceof Flux).as("Expected Flux Publisher: " + target.getClass().getName()).isTrue(); - assertThat(((Flux) target).collectList().block(Duration.ofMillis(1000))).isEqualTo(sequence); + assertThat(((Flux) target).collectList().block(ONE_SECOND)).isEqualTo(sequence); } @Test @@ -244,7 +249,7 @@ void fromSingle() { Object source = io.reactivex.Single.just(1); Object target = getAdapter(io.reactivex.Single.class).toPublisher(source); assertThat(target instanceof Mono).as("Expected Mono Publisher: " + target.getClass().getName()).isTrue(); - assertThat(((Mono) target).block(Duration.ofMillis(1000))).isEqualTo(Integer.valueOf(1)); + assertThat(((Mono) target).block(ONE_SECOND)).isEqualTo(Integer.valueOf(1)); } @Test @@ -252,7 +257,7 @@ void fromCompletable() { Object source = io.reactivex.Completable.complete(); Object target = getAdapter(io.reactivex.Completable.class).toPublisher(source); assertThat(target instanceof Mono).as("Expected Mono Publisher: " + target.getClass().getName()).isTrue(); - ((Mono) target).block(Duration.ofMillis(1000)); + ((Mono) target).block(ONE_SECOND); } } @@ -310,7 +315,7 @@ void fromFlowable() { Object source = io.reactivex.rxjava3.core.Flowable.fromIterable(sequence); Object target = getAdapter(io.reactivex.rxjava3.core.Flowable.class).toPublisher(source); assertThat(target instanceof Flux).as("Expected Flux Publisher: " + target.getClass().getName()).isTrue(); - assertThat(((Flux) target).collectList().block(Duration.ofMillis(1000))).isEqualTo(sequence); + assertThat(((Flux) target).collectList().block(ONE_SECOND)).isEqualTo(sequence); } @Test @@ -319,7 +324,7 @@ void fromObservable() { Object source = io.reactivex.rxjava3.core.Observable.fromIterable(sequence); Object target = getAdapter(io.reactivex.rxjava3.core.Observable.class).toPublisher(source); assertThat(target instanceof Flux).as("Expected Flux Publisher: " + target.getClass().getName()).isTrue(); - assertThat(((Flux) target).collectList().block(Duration.ofMillis(1000))).isEqualTo(sequence); + assertThat(((Flux) target).collectList().block(ONE_SECOND)).isEqualTo(sequence); } @Test @@ -327,7 +332,7 @@ void fromSingle() { Object source = io.reactivex.rxjava3.core.Single.just(1); Object target = getAdapter(io.reactivex.rxjava3.core.Single.class).toPublisher(source); assertThat(target instanceof Mono).as("Expected Mono Publisher: " + target.getClass().getName()).isTrue(); - assertThat(((Mono) target).block(Duration.ofMillis(1000))).isEqualTo(Integer.valueOf(1)); + assertThat(((Mono) target).block(ONE_SECOND)).isEqualTo(Integer.valueOf(1)); } @Test @@ -335,7 +340,7 @@ void fromCompletable() { Object source = io.reactivex.rxjava3.core.Completable.complete(); Object target = getAdapter(io.reactivex.rxjava3.core.Completable.class).toPublisher(source); assertThat(target instanceof Mono).as("Expected Mono Publisher: " + target.getClass().getName()).isTrue(); - ((Mono) target).block(Duration.ofMillis(1000)); + ((Mono) target).block(ONE_SECOND); } } @@ -357,6 +362,51 @@ void deferred() { } } + @Nested + class Mutiny { + + @Test + void defaultAdapterRegistrations() { + assertThat(getAdapter(io.smallrye.mutiny.Uni.class)).isNotNull(); + assertThat(getAdapter(io.smallrye.mutiny.Multi.class)).isNotNull(); + } + + @Test + void toUni() { + Publisher source = Mono.just(1); + Object target = getAdapter(Uni.class).fromPublisher(source); + assertThat(target).isInstanceOf(Uni.class); + assertThat(((Uni) target).await().atMost(ONE_SECOND)).isEqualTo(Integer.valueOf(1)); + } + + @Test + void fromUni() { + Uni source = Uni.createFrom().item(1); + Object target = getAdapter(Uni.class).toPublisher(source); + assertThat(target).isInstanceOf(Mono.class); + assertThat(((Mono) target).block(ONE_SECOND)).isEqualTo(Integer.valueOf(1)); + } + + @Test + void toMulti() { + List sequence = Arrays.asList(1, 2, 3); + Publisher source = Flux.fromIterable(sequence); + Object target = getAdapter(Multi.class).fromPublisher(source); + assertThat(target).isInstanceOf(Multi.class); + assertThat(((Multi) target).collect().asList().await().atMost(ONE_SECOND)).isEqualTo(sequence); + } + + @Test + void fromMulti() { + List sequence = Arrays.asList(1, 2, 3); + Multi source = Multi.createFrom().iterable(sequence); + Object target = getAdapter(Multi.class).toPublisher(source); + assertThat(target).isInstanceOf(Flux.class); + assertThat(((Flux) target).blockLast(ONE_SECOND)).isEqualTo(Integer.valueOf(3)); + } + + } + private ReactiveAdapter getAdapter(Class reactiveType) { ReactiveAdapter adapter = this.registry.getAdapter(reactiveType); assertThat(adapter).isNotNull(); diff --git a/spring-core/src/test/java/org/springframework/util/ObjectUtilsTests.java b/spring-core/src/test/java/org/springframework/util/ObjectUtilsTests.java index aa6cf358117f..b18710a1bfde 100644 --- a/spring-core/src/test/java/org/springframework/util/ObjectUtilsTests.java +++ b/spring-core/src/test/java/org/springframework/util/ObjectUtilsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -18,7 +18,6 @@ import java.io.IOException; import java.sql.SQLException; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -109,7 +108,7 @@ void isEmptyCollection() { Set set = new HashSet<>(); set.add("foo"); assertThat(isEmpty(set)).isFalse(); - assertThat(isEmpty(Arrays.asList("foo"))).isFalse(); + assertThat(isEmpty(Collections.singletonList("foo"))).isFalse(); } @Test @@ -159,7 +158,7 @@ void toObjectArrayWithNull() { void toObjectArrayWithEmptyPrimitiveArray() { Object[] objects = ObjectUtils.toObjectArray(new byte[] {}); assertThat(objects).isNotNull(); - assertThat(objects.length).isEqualTo(0); + assertThat(objects).hasSize(0); } @Test @@ -179,7 +178,7 @@ void addObjectToArraySunnyDay() { String[] array = new String[] {"foo", "bar"}; String newElement = "baz"; Object[] newArray = ObjectUtils.addObjectToArray(array, newElement); - assertThat(newArray.length).isEqualTo(3); + assertThat(newArray).hasSize(3); assertThat(newArray[2]).isEqualTo(newElement); } @@ -188,7 +187,7 @@ void addObjectToArrayWhenEmpty() { String[] array = new String[0]; String newElement = "foo"; String[] newArray = ObjectUtils.addObjectToArray(array, newElement); - assertThat(newArray.length).isEqualTo(1); + assertThat(newArray).hasSize(1); assertThat(newArray[0]).isEqualTo(newElement); } @@ -198,7 +197,7 @@ void addObjectToSingleNonNullElementArray() { String[] array = new String[] {existingElement}; String newElement = "bar"; String[] newArray = ObjectUtils.addObjectToArray(array, newElement); - assertThat(newArray.length).isEqualTo(2); + assertThat(newArray).hasSize(2); assertThat(newArray[0]).isEqualTo(existingElement); assertThat(newArray[1]).isEqualTo(newElement); } @@ -208,8 +207,8 @@ void addObjectToSingleNullElementArray() { String[] array = new String[] {null}; String newElement = "bar"; String[] newArray = ObjectUtils.addObjectToArray(array, newElement); - assertThat(newArray.length).isEqualTo(2); - assertThat(newArray[0]).isEqualTo(null); + assertThat(newArray).hasSize(2); + assertThat(newArray[0]).isNull(); assertThat(newArray[1]).isEqualTo(newElement); } @@ -217,15 +216,15 @@ void addObjectToSingleNullElementArray() { void addObjectToNullArray() throws Exception { String newElement = "foo"; String[] newArray = ObjectUtils.addObjectToArray(null, newElement); - assertThat(newArray.length).isEqualTo(1); + assertThat(newArray).hasSize(1); assertThat(newArray[0]).isEqualTo(newElement); } @Test void addNullObjectToNullArray() throws Exception { Object[] newArray = ObjectUtils.addObjectToArray(null, null); - assertThat(newArray.length).isEqualTo(1); - assertThat(newArray[0]).isEqualTo(null); + assertThat(newArray).hasSize(1); + assertThat(newArray[0]).isNull(); } @Test @@ -260,7 +259,7 @@ void hashCodeWithDouble() { @Deprecated void hashCodeWithFloat() { float flt = 34.8f; - int expected = (new Float(flt)).hashCode(); + int expected = (Float.valueOf(flt)).hashCode(); assertThat(ObjectUtils.hashCode(flt)).isEqualTo(expected); } @@ -268,7 +267,7 @@ void hashCodeWithFloat() { @Deprecated void hashCodeWithLong() { long lng = 883L; - int expected = (new Long(lng)).hashCode(); + int expected = (Long.valueOf(lng)).hashCode(); assertThat(ObjectUtils.hashCode(lng)).isEqualTo(expected); } @@ -282,7 +281,7 @@ void identityToString() { @Test void identityToStringWithNullObject() { - assertThat(ObjectUtils.identityToString(null)).isEqualTo(""); + assertThat(ObjectUtils.identityToString(null)).isEmpty(); } @Test diff --git a/spring-core/src/test/java/org/springframework/util/StringUtilsTests.java b/spring-core/src/test/java/org/springframework/util/StringUtilsTests.java index 9d81c82d5f1c..2aae6260dd0e 100644 --- a/spring-core/src/test/java/org/springframework/util/StringUtilsTests.java +++ b/spring-core/src/test/java/org/springframework/util/StringUtilsTests.java @@ -402,6 +402,8 @@ void cleanPath() { assertThat(StringUtils.cleanPath("file:.././")).isEqualTo("file:../"); assertThat(StringUtils.cleanPath("file:/mypath/spring.factories")).isEqualTo("file:/mypath/spring.factories"); assertThat(StringUtils.cleanPath("file:///c:/some/../path/the%20file.txt")).isEqualTo("file:///c:/path/the%20file.txt"); + assertThat(StringUtils.cleanPath("jar:file:///c:\\some\\..\\path\\.\\the%20file.txt")).isEqualTo("jar:file:///c:/path/the%20file.txt"); + assertThat(StringUtils.cleanPath("jar:file:///c:/some/../path/./the%20file.txt")).isEqualTo("jar:file:///c:/path/the%20file.txt"); } @Test diff --git a/spring-core/src/testFixtures/java/org/springframework/core/testfixture/Assume.java b/spring-core/src/testFixtures/java/org/springframework/core/testfixture/Assume.java deleted file mode 100644 index 83c3dd8d9e90..000000000000 --- a/spring-core/src/testFixtures/java/org/springframework/core/testfixture/Assume.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2002-2019 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 org.springframework.core.testfixture; - -import org.apache.commons.logging.Log; - -import static org.junit.jupiter.api.Assumptions.assumeFalse; - -/** - * Utility methods that allow JUnit tests to assume certain conditions hold - * {@code true}. If an assumption fails, it means the test should be aborted. - * - * @author Rob Winch - * @author Phillip Webb - * @author Sam Brannen - * @since 3.2 - * @see #notLogging(Log) - * @see EnabledForTestGroups @EnabledForTestGroups - */ -public abstract class Assume { - - /** - * Assume that the specified log is not set to Trace or Debug. - * @param log the log to test - * @throws org.opentest4j.TestAbortedException if the assumption fails - */ - public static void notLogging(Log log) { - assumeFalse(log.isTraceEnabled()); - assumeFalse(log.isDebugEnabled()); - } - -} diff --git a/spring-expression/spring-expression.gradle b/spring-expression/spring-expression.gradle index 9f8299d4db90..920f7c7bc07f 100644 --- a/spring-expression/spring-expression.gradle +++ b/spring-expression/spring-expression.gradle @@ -3,8 +3,8 @@ description = "Spring Expression Language (SpEL)" apply plugin: "kotlin" dependencies { - compile(project(":spring-core")) - testCompile(testFixtures(project(":spring-core"))) - testCompile("org.jetbrains.kotlin:kotlin-reflect") - testCompile("org.jetbrains.kotlin:kotlin-stdlib") + api(project(":spring-core")) + testImplementation(testFixtures(project(":spring-core"))) + testImplementation("org.jetbrains.kotlin:kotlin-reflect") + testImplementation("org.jetbrains.kotlin:kotlin-stdlib") } diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/ConstructorReference.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/ConstructorReference.java index 7ccc4c16d962..d42a375410f6 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/ConstructorReference.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/ConstructorReference.java @@ -57,7 +57,7 @@ */ public class ConstructorReference extends SpelNodeImpl { - private boolean isArrayConstructor = false; + private final boolean isArrayConstructor; @Nullable private SpelNodeImpl[] dimensions; @@ -234,6 +234,7 @@ private TypedValue createArray(ExpressionState state) throws EvaluationException FormatHelper.formatClassNameForMessage( intendedArrayType != null ? intendedArrayType.getClass() : null)); } + String type = (String) intendedArrayType; Class componentType; TypeCode arrayTypeCode = TypeCode.forName(type); @@ -243,7 +244,8 @@ private TypedValue createArray(ExpressionState state) throws EvaluationException else { componentType = arrayTypeCode.getType(); } - Object newArray; + + Object newArray = null; if (!hasInitializer()) { // Confirm all dimensions were specified (for example [3][][5] is missing the 2nd dimension) if (this.dimensions != null) { @@ -252,23 +254,22 @@ private TypedValue createArray(ExpressionState state) throws EvaluationException throw new SpelEvaluationException(getStartPosition(), SpelMessage.MISSING_ARRAY_DIMENSION); } } - } - TypeConverter typeConverter = state.getEvaluationContext().getTypeConverter(); - - // Shortcut for 1 dimensional - if (this.dimensions.length == 1) { - TypedValue o = this.dimensions[0].getTypedValue(state); - int arraySize = ExpressionUtils.toInt(typeConverter, o); - newArray = Array.newInstance(componentType, arraySize); - } - else { - // Multi-dimensional - hold onto your hat! - int[] dims = new int[this.dimensions.length]; - for (int d = 0; d < this.dimensions.length; d++) { - TypedValue o = this.dimensions[d].getTypedValue(state); - dims[d] = ExpressionUtils.toInt(typeConverter, o); + TypeConverter typeConverter = state.getEvaluationContext().getTypeConverter(); + if (this.dimensions.length == 1) { + // Shortcut for 1-dimensional + TypedValue o = this.dimensions[0].getTypedValue(state); + int arraySize = ExpressionUtils.toInt(typeConverter, o); + newArray = Array.newInstance(componentType, arraySize); + } + else { + // Multi-dimensional - hold onto your hat! + int[] dims = new int[this.dimensions.length]; + for (int d = 0; d < this.dimensions.length; d++) { + TypedValue o = this.dimensions[d].getTypedValue(state); + dims[d] = ExpressionUtils.toInt(typeConverter, o); + } + newArray = Array.newInstance(componentType, dims); } - newArray = Array.newInstance(componentType, dims); } } else { diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/IndexingTests.java b/spring-expression/src/test/java/org/springframework/expression/spel/IndexingTests.java index 922ec4a51a02..69bfa4fb4f4c 100644 --- a/spring-expression/src/test/java/org/springframework/expression/spel/IndexingTests.java +++ b/spring-expression/src/test/java/org/springframework/expression/spel/IndexingTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -41,11 +41,11 @@ import static org.assertj.core.api.Assertions.assertThat; @SuppressWarnings("rawtypes") -public class IndexingTests { +class IndexingTests { @Test @SuppressWarnings("unchecked") - public void indexIntoGenericPropertyContainingMap() { + void indexIntoGenericPropertyContainingMap() { Map property = new HashMap<>(); property.put("foo", "bar"); this.property = property; @@ -63,7 +63,7 @@ public void indexIntoGenericPropertyContainingMap() { @Test @SuppressWarnings("unchecked") - public void indexIntoGenericPropertyContainingMapObject() { + void indexIntoGenericPropertyContainingMapObject() { Map> property = new HashMap<>(); Map map = new HashMap<>(); map.put("foo", "bar"); @@ -112,7 +112,7 @@ public Class[] getSpecificTargetClasses() { } @Test - public void setGenericPropertyContainingMap() { + void setGenericPropertyContainingMap() { Map property = new HashMap<>(); property.put("foo", "bar"); this.property = property; @@ -127,7 +127,7 @@ public void setGenericPropertyContainingMap() { } @Test - public void setPropertyContainingMap() { + void setPropertyContainingMap() { Map property = new HashMap<>(); property.put(9, 3); this.parameterizedMap = property; @@ -144,7 +144,7 @@ public void setPropertyContainingMap() { public Map parameterizedMap; @Test - public void setPropertyContainingMapAutoGrow() { + void setPropertyContainingMapAutoGrow() { SpelExpressionParser parser = new SpelExpressionParser(new SpelParserConfiguration(true, false)); Expression expression = parser.parseExpression("parameterizedMap"); assertThat(expression.getValueTypeDescriptor(this).toString()).isEqualTo("java.util.Map"); @@ -156,7 +156,7 @@ public void setPropertyContainingMapAutoGrow() { } @Test - public void indexIntoGenericPropertyContainingList() { + void indexIntoGenericPropertyContainingList() { List property = new ArrayList<>(); property.add("bar"); this.property = property; @@ -169,7 +169,7 @@ public void indexIntoGenericPropertyContainingList() { } @Test - public void setGenericPropertyContainingList() { + void setGenericPropertyContainingList() { List property = new ArrayList<>(); property.add(3); this.property = property; @@ -184,7 +184,7 @@ public void setGenericPropertyContainingList() { } @Test - public void setGenericPropertyContainingListAutogrow() { + void setGenericPropertyContainingListAutogrow() { List property = new ArrayList<>(); this.property = property; SpelExpressionParser parser = new SpelExpressionParser(new SpelParserConfiguration(true, true)); @@ -203,7 +203,7 @@ public void setGenericPropertyContainingListAutogrow() { public List decimals; @Test - public void autoGrowListOfElementsWithoutDefaultConstructor() { + void autoGrowListOfElementsWithoutDefaultConstructor() { this.decimals = new ArrayList<>(); SpelExpressionParser parser = new SpelExpressionParser(new SpelParserConfiguration(true, true)); parser.parseExpression("decimals[0]").setValue(this, "123.4"); @@ -211,7 +211,7 @@ public void autoGrowListOfElementsWithoutDefaultConstructor() { } @Test - public void indexIntoPropertyContainingListContainingNullElement() { + void indexIntoPropertyContainingListContainingNullElement() { this.decimals = new ArrayList<>(); this.decimals.add(null); this.decimals.add(BigDecimal.ONE); @@ -221,7 +221,7 @@ public void indexIntoPropertyContainingListContainingNullElement() { } @Test - public void indexIntoPropertyContainingList() { + void indexIntoPropertyContainingList() { List property = new ArrayList<>(); property.add(3); this.parameterizedList = property; @@ -236,7 +236,7 @@ public void indexIntoPropertyContainingList() { public List parameterizedList; @Test - public void indexIntoPropertyContainingListOfList() { + void indexIntoPropertyContainingListOfList() { List> property = new ArrayList<>(); property.add(Arrays.asList(3)); this.parameterizedListOfList = property; @@ -251,7 +251,7 @@ public void indexIntoPropertyContainingListOfList() { public List> parameterizedListOfList; @Test - public void setPropertyContainingList() { + void setPropertyContainingList() { List property = new ArrayList<>(); property.add(3); this.parameterizedList = property; @@ -266,7 +266,7 @@ public void setPropertyContainingList() { } @Test - public void indexIntoGenericPropertyContainingNullList() { + void indexIntoGenericPropertyContainingNullList() { SpelParserConfiguration configuration = new SpelParserConfiguration(true, true); SpelExpressionParser parser = new SpelExpressionParser(configuration); Expression expression = parser.parseExpression("property"); @@ -282,7 +282,7 @@ public void indexIntoGenericPropertyContainingNullList() { } @Test - public void indexIntoGenericPropertyContainingGrowingList() { + void indexIntoGenericPropertyContainingGrowingList() { List property = new ArrayList<>(); this.property = property; SpelParserConfiguration configuration = new SpelParserConfiguration(true, true); @@ -300,7 +300,7 @@ public void indexIntoGenericPropertyContainingGrowingList() { } @Test - public void indexIntoGenericPropertyContainingGrowingList2() { + void indexIntoGenericPropertyContainingGrowingList2() { List property2 = new ArrayList<>(); this.property2 = property2; SpelParserConfiguration configuration = new SpelParserConfiguration(true, true); @@ -320,7 +320,7 @@ public void indexIntoGenericPropertyContainingGrowingList2() { public List property2; @Test - public void indexIntoGenericPropertyContainingArray() { + void indexIntoGenericPropertyContainingArray() { String[] property = new String[] { "bar" }; this.property = property; SpelExpressionParser parser = new SpelExpressionParser(); @@ -332,7 +332,7 @@ public void indexIntoGenericPropertyContainingArray() { } @Test - public void emptyList() { + void emptyList() { listOfScalarNotGeneric = new ArrayList(); SpelExpressionParser parser = new SpelExpressionParser(); Expression expression = parser.parseExpression("listOfScalarNotGeneric"); @@ -342,7 +342,7 @@ public void emptyList() { @SuppressWarnings("unchecked") @Test - public void resolveCollectionElementType() { + void resolveCollectionElementType() { listNotGeneric = new ArrayList(2); listNotGeneric.add(5); listNotGeneric.add(6); @@ -353,7 +353,7 @@ public void resolveCollectionElementType() { } @Test - public void resolveCollectionElementTypeNull() { + void resolveCollectionElementTypeNull() { SpelExpressionParser parser = new SpelExpressionParser(); Expression expression = parser.parseExpression("listNotGeneric"); assertThat(expression.getValueTypeDescriptor(this).toString()).isEqualTo("@org.springframework.expression.spel.IndexingTests$FieldAnnotation java.util.List"); @@ -370,7 +370,7 @@ public void resolveCollectionElementTypeNull() { @SuppressWarnings("unchecked") @Test - public void resolveMapKeyValueTypes() { + void resolveMapKeyValueTypes() { mapNotGeneric = new HashMap(); mapNotGeneric.put("baseAmount", 3.11); mapNotGeneric.put("bonusAmount", 7.17); @@ -384,12 +384,12 @@ public void resolveMapKeyValueTypes() { @SuppressWarnings("unchecked") @Test - public void testListOfScalar() { + void testListOfScalar() { listOfScalarNotGeneric = new ArrayList(1); listOfScalarNotGeneric.add("5"); SpelExpressionParser parser = new SpelExpressionParser(); Expression expression = parser.parseExpression("listOfScalarNotGeneric[0]"); - assertThat(expression.getValue(this, Integer.class)).isEqualTo(new Integer(5)); + assertThat(expression.getValue(this, Integer.class)).isEqualTo(Integer.valueOf(5)); } public List listOfScalarNotGeneric; @@ -397,7 +397,7 @@ public void testListOfScalar() { @SuppressWarnings("unchecked") @Test - public void testListsOfMap() { + void testListsOfMap() { listOfMapsNotGeneric = new ArrayList(); Map map = new HashMap(); map.put("fruit", "apple"); diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/OperatorTests.java b/spring-expression/src/test/java/org/springframework/expression/spel/OperatorTests.java index 92fef3bec695..baef9bd558c9 100644 --- a/spring-expression/src/test/java/org/springframework/expression/spel/OperatorTests.java +++ b/spring-expression/src/test/java/org/springframework/expression/spel/OperatorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -33,10 +33,10 @@ * @author Juergen Hoeller * @author Giovanni Dall'Oglio Risso */ -public class OperatorTests extends AbstractExpressionTests { +class OperatorTests extends AbstractExpressionTests { @Test - public void testEqual() { + void testEqual() { evaluate("3 == 5", false, Boolean.class); evaluate("5 == 3", false, Boolean.class); evaluate("6 == 6", true, Boolean.class); @@ -85,7 +85,7 @@ public void testEqual() { } @Test - public void testNotEqual() { + void testNotEqual() { evaluate("3 != 5", true, Boolean.class); evaluate("5 != 3", true, Boolean.class); evaluate("6 != 6", false, Boolean.class); @@ -134,7 +134,7 @@ public void testNotEqual() { } @Test - public void testLessThan() { + void testLessThan() { evaluate("5 < 5", false, Boolean.class); evaluate("3 < 5", true, Boolean.class); evaluate("5 < 3", false, Boolean.class); @@ -176,7 +176,7 @@ public void testLessThan() { } @Test - public void testLessThanOrEqual() { + void testLessThanOrEqual() { evaluate("3 <= 5", true, Boolean.class); evaluate("5 <= 3", false, Boolean.class); evaluate("6 <= 6", true, Boolean.class); @@ -225,7 +225,7 @@ public void testLessThanOrEqual() { } @Test - public void testGreaterThan() { + void testGreaterThan() { evaluate("3 > 5", false, Boolean.class); evaluate("5 > 3", true, Boolean.class); evaluate("3L > 5L", false, Boolean.class); @@ -266,7 +266,7 @@ public void testGreaterThan() { } @Test - public void testGreaterThanOrEqual() { + void testGreaterThanOrEqual() { evaluate("3 >= 5", false, Boolean.class); evaluate("5 >= 3", true, Boolean.class); evaluate("6 >= 6", true, Boolean.class); @@ -315,27 +315,27 @@ public void testGreaterThanOrEqual() { } @Test - public void testIntegerLiteral() { + void testIntegerLiteral() { evaluate("3", 3, Integer.class); } @Test - public void testRealLiteral() { + void testRealLiteral() { evaluate("3.5", 3.5d, Double.class); } @Test - public void testMultiplyStringInt() { + void testMultiplyStringInt() { evaluate("'a' * 5", "aaaaa", String.class); } @Test - public void testMultiplyDoubleDoubleGivesDouble() { + void testMultiplyDoubleDoubleGivesDouble() { evaluate("3.0d * 5.0d", 15.0d, Double.class); } @Test - public void testMixedOperandsBigDecimal() { + void testMixedOperandsBigDecimal() { evaluate("3 * new java.math.BigDecimal('5')", new BigDecimal("15"), BigDecimal.class); evaluate("3L * new java.math.BigDecimal('5')", new BigDecimal("15"), BigDecimal.class); evaluate("3.0d * new java.math.BigDecimal('5')", new BigDecimal("15.0"), BigDecimal.class); @@ -361,19 +361,19 @@ public void testMixedOperandsBigDecimal() { } @Test - public void testMathOperatorAdd02() { + void testMathOperatorAdd02() { evaluate("'hello' + ' ' + 'world'", "hello world", String.class); } @Test - public void testMathOperatorsInChains() { + void testMathOperatorsInChains() { evaluate("1+2+3",6,Integer.class); evaluate("2*3*4",24,Integer.class); evaluate("12-1-2",9,Integer.class); } @Test - public void testIntegerArithmetic() { + void testIntegerArithmetic() { evaluate("2 + 4", "6", Integer.class); evaluate("5 - 4", "1", Integer.class); evaluate("3 * 5", 15, Integer.class); @@ -388,7 +388,7 @@ public void testIntegerArithmetic() { } @Test - public void testPlus() throws Exception { + void testPlus() { evaluate("7 + 2", "9", Integer.class); evaluate("3.0f + 5.0f", 8.0f, Float.class); evaluate("3.0d + 5.0d", 8.0d, Double.class); @@ -419,7 +419,7 @@ public void testPlus() throws Exception { } @Test - public void testMinus() throws Exception { + void testMinus() { evaluate("'c' - 2", "a", String.class); evaluate("3.0f - 5.0f", -2.0f, Float.class); evaluateAndCheckError("'ab' - 2", SpelMessage.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES); @@ -437,7 +437,7 @@ public void testMinus() throws Exception { } @Test - public void testModulus() { + void testModulus() { evaluate("3%2",1,Integer.class); evaluate("3L%2L",1L,Long.class); evaluate("3.0f%2.0f",1f,Float.class); @@ -448,7 +448,7 @@ public void testModulus() { } @Test - public void testDivide() { + void testDivide() { evaluate("3.0f / 5.0f", 0.6f, Float.class); evaluate("4L/2L",2L,Long.class); evaluate("3.0f div 5.0f", 0.6f, Float.class); @@ -461,17 +461,17 @@ public void testDivide() { } @Test - public void testMathOperatorDivide_ConvertToDouble() { - evaluateAndAskForReturnType("8/4", new Double(2.0), Double.class); + void testMathOperatorDivide_ConvertToDouble() { + evaluateAndAskForReturnType("8/4", 2.0, Double.class); } @Test - public void testMathOperatorDivide04_ConvertToFloat() { - evaluateAndAskForReturnType("8/4", new Float(2.0), Float.class); + void testMathOperatorDivide04_ConvertToFloat() { + evaluateAndAskForReturnType("8/4", 2.0F, Float.class); } @Test - public void testDoubles() { + void testDoubles() { evaluate("3.0d == 5.0d", false, Boolean.class); evaluate("3.0d == 3.0d", true, Boolean.class); evaluate("3.0d != 5.0d", true, Boolean.class); @@ -484,7 +484,7 @@ public void testDoubles() { } @Test - public void testBigDecimals() { + void testBigDecimals() { evaluate("3 + new java.math.BigDecimal('5')", new BigDecimal("8"), BigDecimal.class); evaluate("3 - new java.math.BigDecimal('5')", new BigDecimal("-2"), BigDecimal.class); evaluate("3 * new java.math.BigDecimal('5')", new BigDecimal("15"), BigDecimal.class); @@ -495,7 +495,7 @@ public void testBigDecimals() { } @Test - public void testOperatorNames() throws Exception { + void testOperatorNames() { Operator node = getOperatorNode((SpelExpression)parser.parseExpression("1==3")); assertThat(node.getOperatorName()).isEqualTo("=="); @@ -534,13 +534,13 @@ public void testOperatorNames() throws Exception { } @Test - public void testOperatorOverloading() { + void testOperatorOverloading() { evaluateAndCheckError("'a' * '2'", SpelMessage.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES); evaluateAndCheckError("'a' ^ '2'", SpelMessage.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES); } @Test - public void testPower() { + void testPower() { evaluate("3^2",9,Integer.class); evaluate("3.0d^2.0d",9.0d,Double.class); evaluate("3L^2L",9L,Long.class); @@ -549,7 +549,7 @@ public void testPower() { } @Test - public void testMixedOperands_FloatsAndDoubles() { + void testMixedOperands_FloatsAndDoubles() { evaluate("3.0d + 5.0f", 8.0d, Double.class); evaluate("3.0D - 5.0f", -2.0d, Double.class); evaluate("3.0f * 5.0d", 15.0d, Double.class); @@ -558,7 +558,7 @@ public void testMixedOperands_FloatsAndDoubles() { } @Test - public void testMixedOperands_DoublesAndInts() { + void testMixedOperands_DoublesAndInts() { evaluate("3.0d + 5", 8.0d, Double.class); evaluate("3.0D - 5", -2.0d, Double.class); evaluate("3.0f * 5", 15.0f, Float.class); @@ -569,7 +569,7 @@ public void testMixedOperands_DoublesAndInts() { } @Test - public void testStrings() { + void testStrings() { evaluate("'abc' == 'abc'", true, Boolean.class); evaluate("'abc' == 'def'", false, Boolean.class); evaluate("'abc' != 'abc'", false, Boolean.class); @@ -577,7 +577,7 @@ public void testStrings() { } @Test - public void testLongs() { + void testLongs() { evaluate("3L == 4L", false, Boolean.class); evaluate("3L == 3L", true, Boolean.class); evaluate("3L != 4L", true, Boolean.class); @@ -588,7 +588,7 @@ public void testLongs() { } @Test - public void testBigIntegers() { + void testBigIntegers() { evaluate("3 + new java.math.BigInteger('5')", new BigInteger("8"), BigInteger.class); evaluate("3 - new java.math.BigInteger('5')", new BigInteger("-2"), BigInteger.class); evaluate("3 * new java.math.BigInteger('5')", new BigInteger("15"), BigInteger.class); diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/SpelCompilationCoverageTests.java b/spring-expression/src/test/java/org/springframework/expression/spel/SpelCompilationCoverageTests.java index 74af20b3f1ed..49fa8c182c44 100644 --- a/spring-expression/src/test/java/org/springframework/expression/spel/SpelCompilationCoverageTests.java +++ b/spring-expression/src/test/java/org/springframework/expression/spel/SpelCompilationCoverageTests.java @@ -128,7 +128,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests { @Test - public void typeReference() throws Exception { + void typeReference() { expression = parse("T(String)"); assertThat(expression.getValue()).isEqualTo(String.class); assertCanCompile(expression); @@ -196,7 +196,7 @@ public void typeReference() throws Exception { @SuppressWarnings("unchecked") @Test - public void operatorInstanceOf() throws Exception { + void operatorInstanceOf() { expression = parse("'xyz' instanceof T(String)"); assertThat(expression.getValue()).isEqualTo(true); assertCanCompile(expression); @@ -245,7 +245,7 @@ public void operatorInstanceOf() throws Exception { } @Test - public void operatorInstanceOf_SPR14250() throws Exception { + void operatorInstanceOf_SPR14250() throws Exception { // primitive left operand - should get boxed, return true expression = parse("3 instanceof T(Integer)"); assertThat(expression.getValue()).isEqualTo(true); @@ -292,7 +292,7 @@ public void operatorInstanceOf_SPR14250() throws Exception { } @Test - public void stringLiteral() throws Exception { + void stringLiteral() throws Exception { expression = parser.parseExpression("'abcde'"); assertThat(expression.getValue(new TestClass1(), String.class)).isEqualTo("abcde"); assertCanCompile(expression); @@ -307,18 +307,18 @@ public void stringLiteral() throws Exception { } @Test - public void nullLiteral() throws Exception { + void nullLiteral() throws Exception { expression = parser.parseExpression("null"); Object resultI = expression.getValue(new TestClass1(), Object.class); assertCanCompile(expression); Object resultC = expression.getValue(new TestClass1(), Object.class); - assertThat(resultI).isEqualTo(null); - assertThat(resultC).isEqualTo(null); - assertThat(resultC).isEqualTo(null); + assertThat(resultI).isNull(); + assertThat(resultC).isNull(); + assertThat(resultC).isNull(); } @Test - public void realLiteral() throws Exception { + void realLiteral() throws Exception { expression = parser.parseExpression("3.4d"); double resultI = expression.getValue(new TestClass1(), Double.TYPE); assertCanCompile(expression); @@ -332,7 +332,7 @@ public void realLiteral() throws Exception { @SuppressWarnings("rawtypes") @Test - public void inlineList() throws Exception { + void inlineList() throws Exception { expression = parser.parseExpression("'abcde'.substring({1,3,4}[0])"); Object o = expression.getValue(); assertThat(o).isEqualTo("bcde"); @@ -371,7 +371,7 @@ public void inlineList() throws Exception { @SuppressWarnings("rawtypes") @Test - public void nestedInlineLists() throws Exception { + void nestedInlineLists() throws Exception { Object o = null; expression = parser.parseExpression("{{1,2,3},{4,5,6},{7,8,9}}"); @@ -446,7 +446,7 @@ public void nestedInlineLists() throws Exception { } @Test - public void intLiteral() throws Exception { + void intLiteral() throws Exception { expression = parser.parseExpression("42"); int resultI = expression.getValue(new TestClass1(), Integer.TYPE); assertCanCompile(expression); @@ -477,7 +477,7 @@ public void intLiteral() throws Exception { } @Test - public void longLiteral() throws Exception { + void longLiteral() throws Exception { expression = parser.parseExpression("99L"); long resultI = expression.getValue(new TestClass1(), Long.TYPE); assertCanCompile(expression); @@ -487,24 +487,24 @@ public void longLiteral() throws Exception { } @Test - public void booleanLiteral() throws Exception { + void booleanLiteral() throws Exception { expression = parser.parseExpression("true"); boolean resultI = expression.getValue(1, Boolean.TYPE); - assertThat(resultI).isEqualTo(true); + assertThat(resultI).isTrue(); assertThat(SpelCompiler.compile(expression)).isTrue(); boolean resultC = expression.getValue(1, Boolean.TYPE); - assertThat(resultC).isEqualTo(true); + assertThat(resultC).isTrue(); expression = parser.parseExpression("false"); resultI = expression.getValue(1, Boolean.TYPE); - assertThat(resultI).isEqualTo(false); + assertThat(resultI).isFalse(); assertThat(SpelCompiler.compile(expression)).isTrue(); resultC = expression.getValue(1, Boolean.TYPE); - assertThat(resultC).isEqualTo(false); + assertThat(resultC).isFalse(); } @Test - public void floatLiteral() throws Exception { + void floatLiteral() throws Exception { expression = parser.parseExpression("3.4f"); float resultI = expression.getValue(new TestClass1(), Float.TYPE); assertCanCompile(expression); @@ -517,42 +517,42 @@ public void floatLiteral() throws Exception { } @Test - public void opOr() throws Exception { + void opOr() throws Exception { Expression expression = parser.parseExpression("false or false"); boolean resultI = expression.getValue(1, Boolean.TYPE); SpelCompiler.compile(expression); boolean resultC = expression.getValue(1, Boolean.TYPE); - assertThat(resultI).isEqualTo(false); - assertThat(resultC).isEqualTo(false); + assertThat(resultI).isFalse(); + assertThat(resultC).isFalse(); expression = parser.parseExpression("false or true"); resultI = expression.getValue(1, Boolean.TYPE); assertCanCompile(expression); resultC = expression.getValue(1, Boolean.TYPE); - assertThat(resultI).isEqualTo(true); - assertThat(resultC).isEqualTo(true); + assertThat(resultI).isTrue(); + assertThat(resultC).isTrue(); expression = parser.parseExpression("true or false"); resultI = expression.getValue(1, Boolean.TYPE); assertCanCompile(expression); resultC = expression.getValue(1, Boolean.TYPE); - assertThat(resultI).isEqualTo(true); - assertThat(resultC).isEqualTo(true); + assertThat(resultI).isTrue(); + assertThat(resultC).isTrue(); expression = parser.parseExpression("true or true"); resultI = expression.getValue(1, Boolean.TYPE); assertCanCompile(expression); resultC = expression.getValue(1, Boolean.TYPE); - assertThat(resultI).isEqualTo(true); - assertThat(resultC).isEqualTo(true); + assertThat(resultI).isTrue(); + assertThat(resultC).isTrue(); TestClass4 tc = new TestClass4(); expression = parser.parseExpression("getfalse() or gettrue()"); resultI = expression.getValue(tc, Boolean.TYPE); assertCanCompile(expression); resultC = expression.getValue(tc, Boolean.TYPE); - assertThat(resultI).isEqualTo(true); - assertThat(resultC).isEqualTo(true); + assertThat(resultI).isTrue(); + assertThat(resultC).isTrue(); // Can't compile this as we aren't going down the getfalse() branch in our evaluation expression = parser.parseExpression("gettrue() or getfalse()"); @@ -584,29 +584,29 @@ public void opAnd() throws Exception { boolean resultI = expression.getValue(1, Boolean.TYPE); SpelCompiler.compile(expression); boolean resultC = expression.getValue(1, Boolean.TYPE); - assertThat(resultI).isEqualTo(false); - assertThat(resultC).isEqualTo(false); + assertThat(resultI).isFalse(); + assertThat(resultC).isFalse(); expression = parser.parseExpression("false and true"); resultI = expression.getValue(1, Boolean.TYPE); SpelCompiler.compile(expression); resultC = expression.getValue(1, Boolean.TYPE); - assertThat(resultI).isEqualTo(false); - assertThat(resultC).isEqualTo(false); + assertThat(resultI).isFalse(); + assertThat(resultC).isFalse(); expression = parser.parseExpression("true and false"); resultI = expression.getValue(1, Boolean.TYPE); SpelCompiler.compile(expression); resultC = expression.getValue(1, Boolean.TYPE); - assertThat(resultI).isEqualTo(false); - assertThat(resultC).isEqualTo(false); + assertThat(resultI).isFalse(); + assertThat(resultC).isFalse(); expression = parser.parseExpression("true and true"); resultI = expression.getValue(1, Boolean.TYPE); SpelCompiler.compile(expression); resultC = expression.getValue(1, Boolean.TYPE); - assertThat(resultI).isEqualTo(true); - assertThat(resultC).isEqualTo(true); + assertThat(resultI).isTrue(); + assertThat(resultC).isTrue(); TestClass4 tc = new TestClass4(); @@ -3481,7 +3481,7 @@ public void constructorReference() throws Exception { assertThat(tc8.s).isEqualTo("123"); assertThat(tc8.d).isCloseTo(4.0d, within(0.5d)); - assertThat(tc8.z).isEqualTo(true); + assertThat(tc8.z).isTrue(); // no-arg ctor expression = parser.parseExpression("new " + testclass8 + "()"); @@ -3507,7 +3507,7 @@ public void constructorReference() throws Exception { } @Test - public void methodReferenceReflectiveMethodSelectionWithVarargs() throws Exception { + void methodReferenceReflectiveMethodSelectionWithVarargs() throws Exception { TestClass10 tc = new TestClass10(); // Should call the non varargs version of concat @@ -3526,11 +3526,11 @@ public void methodReferenceReflectiveMethodSelectionWithVarargs() throws Excepti expression = parser.parseExpression("concat()"); assertCantCompile(expression); expression.getValue(tc); - assertThat(tc.s).isEqualTo(""); + assertThat(tc.s).isEmpty(); assertCanCompile(expression); tc.reset(); expression.getValue(tc); - assertThat(tc.s).isEqualTo(""); + assertThat(tc.s).isEmpty(); tc.reset(); // Should call the non varargs version of concat @@ -3549,27 +3549,27 @@ public void methodReferenceReflectiveMethodSelectionWithVarargs() throws Excepti expression = parser.parseExpression("concat2()"); assertCantCompile(expression); expression.getValue(tc); - assertThat(tc.s).isEqualTo(""); + assertThat(tc.s).isEmpty(); assertCanCompile(expression); tc.reset(); expression.getValue(tc); - assertThat(tc.s).isEqualTo(""); + assertThat(tc.s).isEmpty(); tc.reset(); } @Test - public void methodReferenceVarargs() throws Exception { + void methodReferenceVarargs() { TestClass5 tc = new TestClass5(); // varargs string expression = parser.parseExpression("eleven()"); assertCantCompile(expression); expression.getValue(tc); - assertThat(tc.s).isEqualTo(""); + assertThat(tc.s).isEmpty(); assertCanCompile(expression); tc.reset(); expression.getValue(tc); - assertThat(tc.s).isEqualTo(""); + assertThat(tc.s).isEmpty(); tc.reset(); // varargs string @@ -3840,7 +3840,7 @@ public void methodReferenceVarargs() throws Exception { } @Test - public void methodReference() throws Exception { + void methodReference() { TestClass5 tc = new TestClass5(); // non-static method, no args, void return @@ -3985,7 +3985,7 @@ public void methodReference() throws Exception { } @Test - public void errorHandling() throws Exception { + void errorHandling() { TestClass5 tc = new TestClass5(); // changing target @@ -4040,7 +4040,7 @@ public void errorHandling() throws Exception { } @Test - public void methodReference_staticMethod() throws Exception { + void methodReference_staticMethod() { Expression expression = parser.parseExpression("T(Integer).valueOf(42)"); int resultI = expression.getValue(new TestClass1(), Integer.TYPE); assertCanCompile(expression); @@ -4050,7 +4050,7 @@ public void methodReference_staticMethod() throws Exception { } @Test - public void methodReference_literalArguments_int() throws Exception { + void methodReference_literalArguments_int() { Expression expression = parser.parseExpression("'abcd'.substring(1,3)"); String resultI = expression.getValue(new TestClass1(), String.class); assertCanCompile(expression); @@ -4060,7 +4060,7 @@ public void methodReference_literalArguments_int() throws Exception { } @Test - public void methodReference_simpleInstanceMethodNoArg() throws Exception { + void methodReference_simpleInstanceMethodNoArg() { Expression expression = parser.parseExpression("toString()"); String resultI = expression.getValue(42, String.class); assertCanCompile(expression); @@ -4070,7 +4070,7 @@ public void methodReference_simpleInstanceMethodNoArg() throws Exception { } @Test - public void methodReference_simpleInstanceMethodNoArgReturnPrimitive() throws Exception { + void methodReference_simpleInstanceMethodNoArgReturnPrimitive() { expression = parser.parseExpression("intValue()"); int resultI = expression.getValue(42, Integer.TYPE); assertThat(resultI).isEqualTo(42); @@ -4080,7 +4080,7 @@ public void methodReference_simpleInstanceMethodNoArgReturnPrimitive() throws Ex } @Test - public void methodReference_simpleInstanceMethodOneArgReturnPrimitive1() throws Exception { + void methodReference_simpleInstanceMethodOneArgReturnPrimitive1() { Expression expression = parser.parseExpression("indexOf('b')"); int resultI = expression.getValue("abc", Integer.TYPE); assertCanCompile(expression); @@ -4090,7 +4090,7 @@ public void methodReference_simpleInstanceMethodOneArgReturnPrimitive1() throws } @Test - public void methodReference_simpleInstanceMethodOneArgReturnPrimitive2() throws Exception { + void methodReference_simpleInstanceMethodOneArgReturnPrimitive2() { expression = parser.parseExpression("charAt(2)"); char resultI = expression.getValue("abc", Character.TYPE); assertThat(resultI).isEqualTo('c'); @@ -4100,7 +4100,7 @@ public void methodReference_simpleInstanceMethodOneArgReturnPrimitive2() throws } @Test - public void compoundExpression() throws Exception { + void compoundExpression() { Payload payload = new Payload(); expression = parser.parseExpression("DR[0]"); assertThat(expression.getValue(payload).toString()).isEqualTo("instanceof Two"); @@ -4137,7 +4137,7 @@ public void compoundExpression() throws Exception { } @Test - public void mixingItUp_indexerOpEqTernary() throws Exception { + void mixingItUp_indexerOpEqTernary() { Map m = new HashMap<>(); m.put("andy","778"); @@ -4150,7 +4150,7 @@ public void mixingItUp_indexerOpEqTernary() throws Exception { } @Test - public void propertyReference() throws Exception { + void propertyReference() { TestClass6 tc = new TestClass6(); // non static field @@ -4190,7 +4190,7 @@ public void propertyReference() throws Exception { } @Test - public void propertyReferenceVisibility_SPR12771() { + void propertyReferenceVisibility_SPR12771() { StandardEvaluationContext ctx = new StandardEvaluationContext(); ctx.setVariable("httpServletRequest", HttpServlet3RequestFactory.getOne()); // Without a fix compilation was inserting a checkcast to a private type @@ -4202,7 +4202,7 @@ public void propertyReferenceVisibility_SPR12771() { @SuppressWarnings("unchecked") @Test - public void indexer() throws Exception { + void indexer() { String[] sss = new String[] {"a","b","c"}; Number[] ns = new Number[] {2,8,9}; int[] is = new int[] {8,9,10}; @@ -4509,7 +4509,7 @@ public void indexer() throws Exception { } @Test - public void plusNeedingCheckcast_SPR12426() { + void plusNeedingCheckcast_SPR12426() { expression = parser.parseExpression("object + ' world'"); Object v = expression.getValue(new FooObject()); assertThat(v).isEqualTo("hello world"); @@ -4524,7 +4524,7 @@ public void plusNeedingCheckcast_SPR12426() { } @Test - public void mixingItUp_propertyAccessIndexerOpLtTernaryRootNull() throws Exception { + void mixingItUp_propertyAccessIndexerOpLtTernaryRootNull() { Payload payload = new Payload(); expression = parser.parseExpression("DR[0].three"); @@ -4552,7 +4552,7 @@ public void mixingItUp_propertyAccessIndexerOpLtTernaryRootNull() throws Excepti } @Test - public void variantGetter() throws Exception { + void variantGetter() throws Exception { Payload2Holder holder = new Payload2Holder(); StandardEvaluationContext ctx = new StandardEvaluationContext(); ctx.addPropertyAccessor(new MyAccessor()); @@ -4566,7 +4566,7 @@ public void variantGetter() throws Exception { } @Test - public void compilerWithGenerics_12040() { + void compilerWithGenerics_12040() { expression = parser.parseExpression("payload!=2"); assertThat(expression.getValue(new GenericMessageTestHelper<>(4), Boolean.class)).isTrue(); assertCanCompile(expression); @@ -4675,7 +4675,7 @@ public void compilerWithGenerics_12040() { // The new helper class here uses an upper bound on the generic @Test - public void compilerWithGenerics_12040_2() { + void compilerWithGenerics_12040_2() { expression = parser.parseExpression("payload/2"); assertThat(expression.getValue(new GenericMessageTestHelper2<>(4))).isEqualTo(2); assertCanCompile(expression); @@ -4719,7 +4719,7 @@ public void compilerWithGenerics_12040_2() { // The other numeric operators @Test - public void compilerWithGenerics_12040_3() { + void compilerWithGenerics_12040_3() { expression = parser.parseExpression("payload >= 2"); assertThat(expression.getValue(new GenericMessageTestHelper2<>(4), Boolean.TYPE)).isTrue(); assertCanCompile(expression); @@ -4762,7 +4762,7 @@ public void compilerWithGenerics_12040_3() { } @Test - public void indexerMapAccessor_12045() throws Exception { + void indexerMapAccessor_12045() throws Exception { SpelParserConfiguration spc = new SpelParserConfiguration( SpelCompilerMode.IMMEDIATE,getClass().getClassLoader()); SpelExpressionParser sep = new SpelExpressionParser(spc); @@ -4791,7 +4791,7 @@ public void indexerMapAccessor_12045() throws Exception { } @Test - public void elvisOperator_SPR15192() { + void elvisOperator_SPR15192() { SpelParserConfiguration configuration = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, null); Expression exp; @@ -4875,7 +4875,7 @@ public void elvisOperator_SPR15192() { } @Test - public void elvisOperator_SPR17214() throws Exception { + void elvisOperator_SPR17214() { SpelParserConfiguration spc = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, null); SpelExpressionParser sep = new SpelExpressionParser(spc); @@ -4923,7 +4923,7 @@ public void elvisOperator_SPR17214() throws Exception { } @Test - public void testNullComparison_SPR22358() { + void testNullComparison_SPR22358() { SpelParserConfiguration configuration = new SpelParserConfiguration(SpelCompilerMode.OFF, null); SpelExpressionParser parser = new SpelExpressionParser(configuration); StandardEvaluationContext ctx = new StandardEvaluationContext(); @@ -5004,7 +5004,7 @@ private void verifyCompilationAndBehaviourWithNull2(String expressionText, SpelE } @Test - public void ternaryOperator_SPR15192() { + void ternaryOperator_SPR15192() { SpelParserConfiguration configuration = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, null); Expression exp; StandardEvaluationContext context = new StandardEvaluationContext(); @@ -5048,9 +5048,9 @@ public void ternaryOperator_SPR15192() { // null condition exp = new SpelExpressionParser(configuration).parseExpression("3==3?null:4L"); - assertThat(exp.getValue(context, new Foo(), String.class)).isEqualTo(null); + assertThat(exp.getValue(context, new Foo(), String.class)).isNull(); assertCanCompile(exp); - assertThat(exp.getValue(context, new Foo(), String.class)).isEqualTo(null); + assertThat(exp.getValue(context, new Foo(), String.class)).isNull(); assertIsCompiled(exp); // variable access returning primitive @@ -5078,7 +5078,7 @@ public void ternaryOperator_SPR15192() { } @Test - public void repeatedCompilation() throws Exception { + void repeatedCompilation() throws Exception { // Verifying that after a number of compilations, the classloaders // used to load the compiled expressions are discarded/replaced. // See SpelCompiler.loadClass() @@ -6204,9 +6204,9 @@ public class Reg { public Reg(int v) { this._value = v; - this._valueL = new Long(v); - this._valueD = new Double(v); - this._valueF = new Float(v); + this._valueL = Long.valueOf(v); + this._valueD = (double) v; + this._valueF = (float) v; } public Integer getValue() { @@ -6243,16 +6243,16 @@ public Float getValueF2() { public void setValue(Integer value) { _value = value; - _valueL = value==null?null:new Long(value); - _valueD = value==null?null:new Double(value); - _valueF = value==null?null:new Float(value); + _valueL = value==null?null:Long.valueOf(value); + _valueD = value==null?null:Double.valueOf(value); + _valueF = value==null?null:Float.valueOf(value); } public void setValue2(Integer value) { _value2 = value; - _valueL2 = value==null?null:new Long(value); - _valueD2 = value==null?null:new Double(value); - _valueF2 = value==null?null:new Float(value); + _valueL2 = value==null?null:Long.valueOf(value); + _valueD2 = value==null?null:Double.valueOf(value); + _valueF2 = value==null?null:Float.valueOf(value); } } diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/SpelReproTests.java b/spring-expression/src/test/java/org/springframework/expression/spel/SpelReproTests.java index b114826270b5..09e73591350e 100644 --- a/spring-expression/src/test/java/org/springframework/expression/spel/SpelReproTests.java +++ b/spring-expression/src/test/java/org/springframework/expression/spel/SpelReproTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -74,35 +74,35 @@ * @author Phillip Webb * @author Sam Brannen */ -public class SpelReproTests extends AbstractExpressionTests { +class SpelReproTests extends AbstractExpressionTests { @Test - public void NPE_SPR5661() { + void NPE_SPR5661() { evaluate("joinThreeStrings('a',null,'c')", "anullc", String.class); } @Test - public void SWF1086() { + void SWF1086() { evaluate("printDouble(T(java.math.BigDecimal).valueOf(14.35))", "14.35", String.class); } @Test - public void doubleCoercion() { + void doubleCoercion() { evaluate("printDouble(14.35)", "14.35", String.class); } @Test - public void doubleArrayCoercion() { + void doubleArrayCoercion() { evaluate("printDoubles(getDoublesAsStringList())", "{14.35, 15.45}", String.class); } @Test - public void SPR5899() { + void SPR5899() { StandardEvaluationContext context = new StandardEvaluationContext(new Spr5899Class()); Expression expr = new SpelExpressionParser().parseRaw("tryToInvokeWithNull(12)"); assertThat(expr.getValue(context)).isEqualTo(12); expr = new SpelExpressionParser().parseRaw("tryToInvokeWithNull(null)"); - assertThat(expr.getValue(context)).isEqualTo(null); + assertThat(expr.getValue(context)).isNull(); expr = new SpelExpressionParser().parseRaw("tryToInvokeWithNull2(null)"); assertThatExceptionOfType(EvaluationException.class).isThrownBy( expr::getValue); @@ -133,7 +133,7 @@ public void SPR5899() { } @Test - public void SPR5905_InnerTypeReferences() { + void SPR5905_InnerTypeReferences() { StandardEvaluationContext context = new StandardEvaluationContext(new Spr5899Class()); Expression expr = new SpelExpressionParser().parseRaw("T(java.util.Map$Entry)"); assertThat(expr.getValue(context)).isEqualTo(Map.Entry.class); @@ -146,7 +146,7 @@ public void SPR5905_InnerTypeReferences() { } @Test - public void SPR5804() { + void SPR5804() { Map m = new HashMap<>(); m.put("foo", "bar"); StandardEvaluationContext context = new StandardEvaluationContext(m); // root is a map instance @@ -156,7 +156,7 @@ public void SPR5804() { } @Test - public void SPR5847() { + void SPR5847() { StandardEvaluationContext context = new StandardEvaluationContext(new TestProperties()); String name = null; Expression expr = null; @@ -192,7 +192,7 @@ public void SPR5847() { } @Test - public void NPE_SPR5673() { + void NPE_SPR5673() { ParserContext hashes = TemplateExpressionParsingTests.HASH_DELIMITED_PARSER_CONTEXT; ParserContext dollars = TemplateExpressionParsingTests.DEFAULT_TEMPLATE_PARSER_CONTEXT; @@ -227,7 +227,7 @@ public void NPE_SPR5673() { } @Test - public void propertyAccessOnNullTarget_SPR5663() throws AccessException { + void propertyAccessOnNullTarget_SPR5663() throws AccessException { PropertyAccessor accessor = new ReflectivePropertyAccessor(); EvaluationContext context = TestScenarioCreator.getTestEvaluationContext(); assertThat(accessor.canRead(context, null, "abc")).isFalse(); @@ -239,7 +239,7 @@ public void propertyAccessOnNullTarget_SPR5663() throws AccessException { } @Test - public void nestedProperties_SPR6923() { + void nestedProperties_SPR6923() { StandardEvaluationContext context = new StandardEvaluationContext(new Foo()); Expression expr = new SpelExpressionParser().parseRaw("resource.resource.server"); String name = expr.getValue(context, String.class); @@ -248,7 +248,7 @@ public void nestedProperties_SPR6923() { /** Should be accessing Goo.getKey because 'bar' field evaluates to "key" */ @Test - public void indexingAsAPropertyAccess_SPR6968_1() { + void indexingAsAPropertyAccess_SPR6968_1() { StandardEvaluationContext context = new StandardEvaluationContext(new Goo()); String name = null; Expression expr = null; @@ -261,7 +261,7 @@ public void indexingAsAPropertyAccess_SPR6968_1() { /** Should be accessing Goo.getKey because 'bar' variable evaluates to "key" */ @Test - public void indexingAsAPropertyAccess_SPR6968_2() { + void indexingAsAPropertyAccess_SPR6968_2() { StandardEvaluationContext context = new StandardEvaluationContext(new Goo()); context.setVariable("bar", "key"); String name = null; @@ -275,7 +275,7 @@ public void indexingAsAPropertyAccess_SPR6968_2() { /** $ related identifiers */ @Test - public void dollarPrefixedIdentifier_SPR7100() { + void dollarPrefixedIdentifier_SPR7100() { Holder h = new Holder(); StandardEvaluationContext context = new StandardEvaluationContext(h); context.addPropertyAccessor(new MapAccessor()); @@ -315,7 +315,7 @@ public void dollarPrefixedIdentifier_SPR7100() { /** Should be accessing Goo.wibble field because 'bar' variable evaluates to "wibble" */ @Test - public void indexingAsAPropertyAccess_SPR6968_3() { + void indexingAsAPropertyAccess_SPR6968_3() { StandardEvaluationContext context = new StandardEvaluationContext(new Goo()); context.setVariable("bar", "wibble"); String name = null; @@ -333,7 +333,7 @@ public void indexingAsAPropertyAccess_SPR6968_3() { * "wibble" */ @Test - public void indexingAsAPropertyAccess_SPR6968_4() { + void indexingAsAPropertyAccess_SPR6968_4() { Goo g = Goo.instance; StandardEvaluationContext context = new StandardEvaluationContext(g); context.setVariable("bar", "wibble"); @@ -348,7 +348,7 @@ public void indexingAsAPropertyAccess_SPR6968_4() { /** Should be accessing Goo.setKey field because 'bar' variable evaluates to "key" */ @Test - public void indexingAsAPropertyAccess_SPR6968_5() { + void indexingAsAPropertyAccess_SPR6968_5() { Goo g = Goo.instance; StandardEvaluationContext context = new StandardEvaluationContext(g); Expression expr = null; @@ -360,7 +360,7 @@ public void indexingAsAPropertyAccess_SPR6968_5() { } @Test - public void dollars() { + void dollars() { StandardEvaluationContext context = new StandardEvaluationContext(new XX()); Expression expr = null; expr = new SpelExpressionParser().parseRaw("m['$foo']"); @@ -369,7 +369,7 @@ public void dollars() { } @Test - public void dollars2() { + void dollars2() { StandardEvaluationContext context = new StandardEvaluationContext(new XX()); Expression expr = null; expr = new SpelExpressionParser().parseRaw("m[$foo]"); @@ -421,7 +421,7 @@ public boolean isTemplate() { }; @Test - public void beanResolution() { + void beanResolution() { StandardEvaluationContext context = new StandardEvaluationContext(new XX()); Expression expr = null; @@ -443,12 +443,12 @@ public void beanResolution() { // bean does not exist expr = new SpelExpressionParser().parseRaw("@bar"); - assertThat(expr.getValue(context, String.class)).isEqualTo(null); + assertThat(expr.getValue(context, String.class)).isNull(); // bean name will cause AccessException expr = new SpelExpressionParser().parseRaw("@goo"); try { - assertThat(expr.getValue(context, String.class)).isEqualTo(null); + assertThat(expr.getValue(context, String.class)).isNull(); } catch (SpelEvaluationException see) { assertThat(see.getMessageCode()).isEqualTo(SpelMessage.EXCEPTION_DURING_BEAN_RESOLUTION); @@ -472,7 +472,7 @@ public void beanResolution() { } @Test - public void elvis_SPR7209_1() { + void elvis_SPR7209_1() { StandardEvaluationContext context = new StandardEvaluationContext(new XX()); Expression expr = null; @@ -482,14 +482,14 @@ public void elvis_SPR7209_1() { expr = new SpelExpressionParser().parseRaw("?:'default'"); assertThat(expr.getValue()).isEqualTo("default"); expr = new SpelExpressionParser().parseRaw("?:"); - assertThat(expr.getValue()).isEqualTo(null); + assertThat(expr.getValue()).isNull(); // Different parts of ternary expression are null assertThatExceptionOfType(SpelEvaluationException.class).isThrownBy(() -> new SpelExpressionParser().parseRaw("(?'abc':'default')").getValue(context)) .satisfies(ex -> assertThat(ex.getMessageCode()).isEqualTo(SpelMessage.TYPE_CONVERSION_ERROR)); expr = new SpelExpressionParser().parseRaw("(false?'abc':null)"); - assertThat(expr.getValue()).isEqualTo(null); + assertThat(expr.getValue()).isNull(); // Assignment assertThatExceptionOfType(SpelEvaluationException.class).isThrownBy(() -> @@ -498,7 +498,7 @@ public void elvis_SPR7209_1() { } @Test - public void elvis_SPR7209_2() { + void elvis_SPR7209_2() { Expression expr = null; // Have empty string treated as null for elvis expr = new SpelExpressionParser().parseRaw("?:'default'"); @@ -510,7 +510,7 @@ public void elvis_SPR7209_2() { } @Test - public void mapOfMap_SPR7244() { + void mapOfMap_SPR7244() { Map map = new LinkedHashMap<>(); map.put("uri", "http:"); Map nameMap = new LinkedHashMap<>(); @@ -531,7 +531,7 @@ public void mapOfMap_SPR7244() { } @Test - public void projectionTypeDescriptors_1() { + void projectionTypeDescriptors_1() { StandardEvaluationContext context = new StandardEvaluationContext(new C()); SpelExpressionParser parser = new SpelExpressionParser(); String el1 = "ls.![#this.equals('abc')]"; @@ -540,11 +540,11 @@ public void projectionTypeDescriptors_1() { // value is list containing [true,false] assertThat(value.get(0).getClass()).isEqualTo(Boolean.class); TypeDescriptor evaluated = exp.getValueTypeDescriptor(context); - assertThat(evaluated.getElementTypeDescriptor()).isEqualTo(null); + assertThat(evaluated.getElementTypeDescriptor()).isNull(); } @Test - public void projectionTypeDescriptors_2() { + void projectionTypeDescriptors_2() { StandardEvaluationContext context = new StandardEvaluationContext(new C()); SpelExpressionParser parser = new SpelExpressionParser(); String el1 = "as.![#this.equals('abc')]"; @@ -557,7 +557,7 @@ public void projectionTypeDescriptors_2() { } @Test - public void projectionTypeDescriptors_3() { + void projectionTypeDescriptors_3() { StandardEvaluationContext context = new StandardEvaluationContext(new C()); SpelExpressionParser parser = new SpelExpressionParser(); String el1 = "ms.![key.equals('abc')]"; @@ -566,11 +566,11 @@ public void projectionTypeDescriptors_3() { // value is list containing [true,false] assertThat(value.get(0).getClass()).isEqualTo(Boolean.class); TypeDescriptor evaluated = exp.getValueTypeDescriptor(context); - assertThat(evaluated.getElementTypeDescriptor()).isEqualTo(null); + assertThat(evaluated.getElementTypeDescriptor()).isNull(); } @Test - public void greaterThanWithNulls_SPR7840() { + void greaterThanWithNulls_SPR7840() { List list = new ArrayList<>(); list.add(new D("aaa")); list.add(new D("bbb")); @@ -605,7 +605,7 @@ public void greaterThanWithNulls_SPR7840() { * than a unboxing conversion. */ @Test - public void conversionPriority_SPR8224() throws Exception { + void conversionPriority_SPR8224() throws Exception { @SuppressWarnings("unused") class ConversionPriority1 { @@ -637,7 +637,7 @@ public int getX(Number i) { ConversionPriority1 target = new ConversionPriority1(); MethodExecutor me = new ReflectiveMethodResolver(true).resolve(emptyEvalContext, target, "getX", args); // MethodInvoker chooses getX(int i) when passing Integer - final int actual = (Integer) me.execute(emptyEvalContext, target, new Integer(42)).getValue(); + final int actual = (Integer) me.execute(emptyEvalContext, target, Integer.valueOf(42)).getValue(); // Compiler chooses getX(Number i) when passing Integer final int compiler = target.getX(INTEGER); // Fails! @@ -646,7 +646,7 @@ public int getX(Number i) { ConversionPriority2 target2 = new ConversionPriority2(); MethodExecutor me2 = new ReflectiveMethodResolver(true).resolve(emptyEvalContext, target2, "getX", args); // MethodInvoker chooses getX(int i) when passing Integer - int actual2 = (Integer) me2.execute(emptyEvalContext, target2, new Integer(42)).getValue(); + int actual2 = (Integer) me2.execute(emptyEvalContext, target2, Integer.valueOf(42)).getValue(); // Compiler chooses getX(Number i) when passing Integer int compiler2 = target2.getX(INTEGER); // Fails! @@ -659,7 +659,7 @@ public int getX(Number i) { * method accepting 'long' is ok. */ @Test - public void wideningPrimitiveConversion_SPR8224() throws Exception { + void wideningPrimitiveConversion_SPR8224() throws Exception { class WideningPrimitiveConversion { public int getX(long i) { @@ -667,7 +667,7 @@ public int getX(long i) { } } - final Integer INTEGER_VALUE = Integer.valueOf(7); + final Integer INTEGER_VALUE = 7; WideningPrimitiveConversion target = new WideningPrimitiveConversion(); EvaluationContext emptyEvalContext = new StandardEvaluationContext(); @@ -682,7 +682,7 @@ public int getX(long i) { } @Test - public void varargsAgainstProxy_SPR16122() { + void varargsAgainstProxy_SPR16122() { SpelExpressionParser parser = new SpelExpressionParser(); Expression expr = parser.parseExpression("process('a', 'b')"); @@ -696,7 +696,7 @@ public void varargsAgainstProxy_SPR16122() { } @Test - public void testCompiledExpressionForProxy_SPR16191() { + void testCompiledExpressionForProxy_SPR16191() { SpelExpressionParser expressionParser = new SpelExpressionParser(new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, null)); Expression expression = expressionParser.parseExpression("#target.process(#root)"); @@ -715,7 +715,7 @@ public void testCompiledExpressionForProxy_SPR16191() { } @Test - public void varargsAndPrimitives_SPR8174() throws Exception { + void varargsAndPrimitives_SPR8174() throws Exception { EvaluationContext emptyEvalContext = new StandardEvaluationContext(); List args = new ArrayList<>(); @@ -763,7 +763,7 @@ public void varargsAndPrimitives_SPR8174() throws Exception { } @Test - public void reservedWords_SPR8228() { + void reservedWords_SPR8228() { // "DIV","EQ","GE","GT","LE","LT","MOD","NE","NOT" @SuppressWarnings("unused") @@ -814,7 +814,7 @@ public Reserver getReserver() { } @Test - public void reservedWordProperties_SPR9862() { + void reservedWordProperties_SPR9862() { StandardEvaluationContext context = new StandardEvaluationContext(); SpelExpressionParser parser = new SpelExpressionParser(); SpelExpression expression = parser.parseRaw("T(org.springframework.expression.spel.testresources.le.div.mod.reserved.Reserver).CONST"); @@ -829,7 +829,7 @@ public void reservedWordProperties_SPR9862() { * in evaluation of SPEL expressions for a given context. */ @Test - public void propertyAccessorOrder_SPR8211() { + void propertyAccessorOrder_SPR8211() { ExpressionParser expressionParser = new SpelExpressionParser(); StandardEvaluationContext evaluationContext = new StandardEvaluationContext(new ContextObject()); @@ -849,7 +849,7 @@ public void propertyAccessorOrder_SPR8211() { * determines the set of methods for a type. */ @Test - public void customStaticFunctions_SPR9038() { + void customStaticFunctions_SPR9038() { ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); List methodResolvers = new ArrayList<>(); @@ -873,7 +873,7 @@ protected Method[] getMethods(Class type) { } @Test - public void array() { + void array() { ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); Expression expression = null; @@ -902,7 +902,7 @@ public void array() { } @Test - public void SPR9486_floatFunctionResolver() { + void SPR9486_floatFunctionResolver() { Number expectedResult = Math.abs(-10.2f); ExpressionParser parser = new SpelExpressionParser(); SPR9486_FunctionsClass testObject = new SPR9486_FunctionsClass(); @@ -914,7 +914,7 @@ public void SPR9486_floatFunctionResolver() { } @Test - public void SPR9486_addFloatWithDouble() { + void SPR9486_addFloatWithDouble() { Number expectedNumber = 10.21f + 10.2; ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); @@ -924,7 +924,7 @@ public void SPR9486_addFloatWithDouble() { } @Test - public void SPR9486_addFloatWithFloat() { + void SPR9486_addFloatWithFloat() { Number expectedNumber = 10.21f + 10.2f; ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); @@ -934,7 +934,7 @@ public void SPR9486_addFloatWithFloat() { } @Test - public void SPR9486_subtractFloatWithDouble() { + void SPR9486_subtractFloatWithDouble() { Number expectedNumber = 10.21f - 10.2; ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); @@ -944,7 +944,7 @@ public void SPR9486_subtractFloatWithDouble() { } @Test - public void SPR9486_subtractFloatWithFloat() { + void SPR9486_subtractFloatWithFloat() { Number expectedNumber = 10.21f - 10.2f; ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); @@ -954,7 +954,7 @@ public void SPR9486_subtractFloatWithFloat() { } @Test - public void SPR9486_multiplyFloatWithDouble() { + void SPR9486_multiplyFloatWithDouble() { Number expectedNumber = 10.21f * 10.2; ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); @@ -964,7 +964,7 @@ public void SPR9486_multiplyFloatWithDouble() { } @Test - public void SPR9486_multiplyFloatWithFloat() { + void SPR9486_multiplyFloatWithFloat() { Number expectedNumber = 10.21f * 10.2f; ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); @@ -974,7 +974,7 @@ public void SPR9486_multiplyFloatWithFloat() { } @Test - public void SPR9486_floatDivideByFloat() { + void SPR9486_floatDivideByFloat() { Number expectedNumber = -10.21f / -10.2f; ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); @@ -984,7 +984,7 @@ public void SPR9486_floatDivideByFloat() { } @Test - public void SPR9486_floatDivideByDouble() { + void SPR9486_floatDivideByDouble() { Number expectedNumber = -10.21f / -10.2; ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); @@ -994,7 +994,7 @@ public void SPR9486_floatDivideByDouble() { } @Test - public void SPR9486_floatEqFloatUnaryMinus() { + void SPR9486_floatEqFloatUnaryMinus() { Boolean expectedResult = -10.21f == -10.2f; ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); @@ -1004,7 +1004,7 @@ public void SPR9486_floatEqFloatUnaryMinus() { } @Test - public void SPR9486_floatEqDoubleUnaryMinus() { + void SPR9486_floatEqDoubleUnaryMinus() { Boolean expectedResult = -10.21f == -10.2; ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); @@ -1014,7 +1014,7 @@ public void SPR9486_floatEqDoubleUnaryMinus() { } @Test - public void SPR9486_floatEqFloat() { + void SPR9486_floatEqFloat() { Boolean expectedResult = 10.215f == 10.2109f; ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); @@ -1024,7 +1024,7 @@ public void SPR9486_floatEqFloat() { } @Test - public void SPR9486_floatEqDouble() { + void SPR9486_floatEqDouble() { Boolean expectedResult = 10.215f == 10.2109; ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); @@ -1034,7 +1034,7 @@ public void SPR9486_floatEqDouble() { } @Test - public void SPR9486_floatNotEqFloat() { + void SPR9486_floatNotEqFloat() { Boolean expectedResult = 10.215f != 10.2109f; ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); @@ -1044,7 +1044,7 @@ public void SPR9486_floatNotEqFloat() { } @Test - public void SPR9486_floatNotEqDouble() { + void SPR9486_floatNotEqDouble() { Boolean expectedResult = 10.215f != 10.2109; ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); @@ -1054,7 +1054,7 @@ public void SPR9486_floatNotEqDouble() { } @Test - public void SPR9486_floatLessThanFloat() { + void SPR9486_floatLessThanFloat() { Boolean expectedNumber = -10.21f < -10.2f; ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); @@ -1064,7 +1064,7 @@ public void SPR9486_floatLessThanFloat() { } @Test - public void SPR9486_floatLessThanDouble() { + void SPR9486_floatLessThanDouble() { Boolean expectedNumber = -10.21f < -10.2; ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); @@ -1074,7 +1074,7 @@ public void SPR9486_floatLessThanDouble() { } @Test - public void SPR9486_floatLessThanOrEqualFloat() { + void SPR9486_floatLessThanOrEqualFloat() { Boolean expectedNumber = -10.21f <= -10.22f; ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); @@ -1084,7 +1084,7 @@ public void SPR9486_floatLessThanOrEqualFloat() { } @Test - public void SPR9486_floatLessThanOrEqualDouble() { + void SPR9486_floatLessThanOrEqualDouble() { Boolean expectedNumber = -10.21f <= -10.2; ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); @@ -1094,7 +1094,7 @@ public void SPR9486_floatLessThanOrEqualDouble() { } @Test - public void SPR9486_floatGreaterThanFloat() { + void SPR9486_floatGreaterThanFloat() { Boolean expectedNumber = -10.21f > -10.2f; ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); @@ -1104,7 +1104,7 @@ public void SPR9486_floatGreaterThanFloat() { } @Test - public void SPR9486_floatGreaterThanDouble() { + void SPR9486_floatGreaterThanDouble() { Boolean expectedResult = -10.21f > -10.2; ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); @@ -1114,7 +1114,7 @@ public void SPR9486_floatGreaterThanDouble() { } @Test - public void SPR9486_floatGreaterThanOrEqualFloat() { + void SPR9486_floatGreaterThanOrEqualFloat() { Boolean expectedNumber = -10.21f >= -10.2f; ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); @@ -1124,7 +1124,7 @@ public void SPR9486_floatGreaterThanOrEqualFloat() { } @Test - public void SPR9486_floatGreaterThanEqualDouble() { + void SPR9486_floatGreaterThanEqualDouble() { Boolean expectedResult = -10.21f >= -10.2; ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); @@ -1134,7 +1134,7 @@ public void SPR9486_floatGreaterThanEqualDouble() { } @Test - public void SPR9486_floatModulusFloat() { + void SPR9486_floatModulusFloat() { Number expectedResult = 10.21f % 10.2f; ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); @@ -1144,7 +1144,7 @@ public void SPR9486_floatModulusFloat() { } @Test - public void SPR9486_floatModulusDouble() { + void SPR9486_floatModulusDouble() { Number expectedResult = 10.21f % 10.2; ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); @@ -1154,7 +1154,7 @@ public void SPR9486_floatModulusDouble() { } @Test - public void SPR9486_floatPowerFloat() { + void SPR9486_floatPowerFloat() { Number expectedResult = Math.pow(10.21f, -10.2f); ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); @@ -1164,7 +1164,7 @@ public void SPR9486_floatPowerFloat() { } @Test - public void SPR9486_floatPowerDouble() { + void SPR9486_floatPowerDouble() { Number expectedResult = Math.pow(10.21f, 10.2); ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); @@ -1174,7 +1174,7 @@ public void SPR9486_floatPowerDouble() { } @Test - public void SPR9994_bridgeMethods() throws Exception { + void SPR9994_bridgeMethods() throws Exception { ReflectivePropertyAccessor accessor = new ReflectivePropertyAccessor(); StandardEvaluationContext context = new StandardEvaluationContext(); GenericImplementation target = new GenericImplementation(); @@ -1187,7 +1187,7 @@ public void SPR9994_bridgeMethods() throws Exception { } @Test - public void SPR10162_onlyBridgeMethod() throws Exception { + void SPR10162_onlyBridgeMethod() throws Exception { ReflectivePropertyAccessor accessor = new ReflectivePropertyAccessor(); StandardEvaluationContext context = new StandardEvaluationContext(); Object target = new OnlyBridgeMethod(); @@ -1197,7 +1197,7 @@ public void SPR10162_onlyBridgeMethod() throws Exception { } @Test - public void SPR10091_simpleTestValueType() { + void SPR10091_simpleTestValueType() { ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext evaluationContext = new StandardEvaluationContext(new BooleanHolder()); Class valueType = parser.parseExpression("simpleProperty").getValueType(evaluationContext); @@ -1205,7 +1205,7 @@ public void SPR10091_simpleTestValueType() { } @Test - public void SPR10091_simpleTestValue() { + void SPR10091_simpleTestValue() { ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext evaluationContext = new StandardEvaluationContext(new BooleanHolder()); Object value = parser.parseExpression("simpleProperty").getValue(evaluationContext); @@ -1213,7 +1213,7 @@ public void SPR10091_simpleTestValue() { } @Test - public void SPR10091_primitiveTestValueType() { + void SPR10091_primitiveTestValueType() { ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext evaluationContext = new StandardEvaluationContext(new BooleanHolder()); Class valueType = parser.parseExpression("primitiveProperty").getValueType(evaluationContext); @@ -1221,7 +1221,7 @@ public void SPR10091_primitiveTestValueType() { } @Test - public void SPR10091_primitiveTestValue() { + void SPR10091_primitiveTestValue() { ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext evaluationContext = new StandardEvaluationContext(new BooleanHolder()); Object value = parser.parseExpression("primitiveProperty").getValue(evaluationContext); @@ -1229,7 +1229,7 @@ public void SPR10091_primitiveTestValue() { } @Test - public void SPR16123() { + void SPR16123() { ExpressionParser parser = new SpelExpressionParser(); parser.parseExpression("simpleProperty").setValue(new BooleanHolder(), null); assertThatExceptionOfType(EvaluationException.class).isThrownBy(() -> @@ -1237,7 +1237,7 @@ public void SPR16123() { } @Test - public void SPR10146_malformedExpressions() { + void SPR10146_malformedExpressions() { doTestSpr10146("/foo", "EL1070E: Problem parsing left operand"); doTestSpr10146("*foo", "EL1070E: Problem parsing left operand"); doTestSpr10146("%foo", "EL1070E: Problem parsing left operand"); @@ -1255,7 +1255,7 @@ private void doTestSpr10146(String expression, String expectedMessage) { } @Test - public void SPR10125() { + void SPR10125() { StandardEvaluationContext context = new StandardEvaluationContext(); String fromInterface = parser.parseExpression("T(" + StaticFinalImpl1.class.getName() + ").VALUE").getValue( context, String.class); @@ -1266,7 +1266,7 @@ public void SPR10125() { } @Test - public void SPR10210() { + void SPR10210() { StandardEvaluationContext context = new StandardEvaluationContext(); context.setVariable("bridgeExample", new org.springframework.expression.spel.spr10210.D()); Expression parseExpression = parser.parseExpression("#bridgeExample.bridgeMethod()"); @@ -1274,14 +1274,14 @@ public void SPR10210() { } @Test - public void SPR10328() { + void SPR10328() { assertThatExceptionOfType(SpelParseException.class).isThrownBy(() -> parser.parseExpression("$[]")) .withMessageContaining("EL1071E: A required selection expression has not been specified"); } @Test - public void SPR10452() { + void SPR10452() { SpelParserConfiguration configuration = new SpelParserConfiguration(false, false); ExpressionParser parser = new SpelExpressionParser(configuration); @@ -1306,7 +1306,7 @@ public void SPR10452() { } @Test - public void SPR9495() { + void SPR9495() { SpelParserConfiguration configuration = new SpelParserConfiguration(false, false); ExpressionParser parser = new SpelExpressionParser(configuration); @@ -1347,7 +1347,7 @@ public MethodExecutor resolve(EvaluationContext context, Object targetObject, St } @Test - public void SPR10486() { + void SPR10486() { SpelExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); Spr10486 rootObject = new Spr10486(); @@ -1358,7 +1358,7 @@ public void SPR10486() { } @Test - public void SPR11142() { + void SPR11142() { SpelExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); Spr11142 rootObject = new Spr11142(); @@ -1369,7 +1369,7 @@ public void SPR11142() { } @Test - public void SPR9194() { + void SPR9194() { TestClass2 one = new TestClass2("abc"); TestClass2 two = new TestClass2("abc"); Map map = new HashMap<>(); @@ -1382,7 +1382,7 @@ public void SPR9194() { } @Test - public void SPR11348() { + void SPR11348() { Collection coll = new LinkedHashSet<>(); coll.add("one"); coll.add("two"); @@ -1399,14 +1399,14 @@ public void SPR11348() { } @Test - public void SPR11445_simple() { + void SPR11445_simple() { StandardEvaluationContext context = new StandardEvaluationContext(new Spr11445Class()); Expression expr = new SpelExpressionParser().parseRaw("echo(parameter())"); assertThat(expr.getValue(context)).isEqualTo(1); } @Test - public void SPR11445_beanReference() { + void SPR11445_beanReference() { StandardEvaluationContext context = new StandardEvaluationContext(); context.setBeanResolver(new Spr11445Class()); Expression expr = new SpelExpressionParser().parseRaw("@bean.echo(@bean.parameter())"); @@ -1415,14 +1415,14 @@ public void SPR11445_beanReference() { @Test @SuppressWarnings("unchecked") - public void SPR11494() { + void SPR11494() { Expression exp = new SpelExpressionParser().parseExpression("T(java.util.Arrays).asList('a','b')"); List list = (List) exp.getValue(); assertThat(list).hasSize(2); } @Test - public void SPR11609() { + void SPR11609() { StandardEvaluationContext sec = new StandardEvaluationContext(); sec.addPropertyAccessor(new MapAccessor()); Expression exp = new SpelExpressionParser().parseExpression( @@ -1431,7 +1431,7 @@ public void SPR11609() { } @Test - public void SPR9735() { + void SPR9735() { Item item = new Item(); item.setName("parent"); @@ -1453,7 +1453,7 @@ public void SPR9735() { } @Test - public void SPR12502() { + void SPR12502() { SpelExpressionParser parser = new SpelExpressionParser(); Expression expression = parser.parseExpression("#root.getClass().getName()"); assertThat(expression.getValue(new UnnamedUser())).isEqualTo(UnnamedUser.class.getName()); @@ -1462,7 +1462,7 @@ public void SPR12502() { @Test @SuppressWarnings("rawtypes") - public void SPR12522() { + void SPR12522() { SpelExpressionParser parser = new SpelExpressionParser(); Expression expression = parser.parseExpression("T(java.util.Arrays).asList('')"); Object value = expression.getValue(); @@ -1471,7 +1471,7 @@ public void SPR12522() { } @Test - public void SPR12803() { + void SPR12803() { StandardEvaluationContext sec = new StandardEvaluationContext(); sec.setVariable("iterable", Collections.emptyList()); SpelExpressionParser parser = new SpelExpressionParser(); @@ -1480,7 +1480,7 @@ public void SPR12803() { } @Test - public void SPR12808() { + void SPR12808() { SpelExpressionParser parser = new SpelExpressionParser(); Expression expression = parser.parseExpression("T(org.springframework.expression.spel.SpelReproTests.DistanceEnforcer).from(#no)"); StandardEvaluationContext sec = new StandardEvaluationContext(); @@ -1496,7 +1496,7 @@ public void SPR12808() { @Test @SuppressWarnings("rawtypes") - public void SPR13055() { + void SPR13055() { List> myPayload = new ArrayList<>(); Map v1 = new HashMap<>(); @@ -1527,7 +1527,7 @@ public void SPR13055() { } @Test - public void AccessingFactoryBean_spr9511() { + void AccessingFactoryBean_spr9511() { StandardEvaluationContext context = new StandardEvaluationContext(); context.setBeanResolver(new MyBeanResolver()); Expression expr = new SpelExpressionParser().parseRaw("@foo"); @@ -1551,7 +1551,7 @@ public void AccessingFactoryBean_spr9511() { } @Test - public void SPR12035() { + void SPR12035() { ExpressionParser parser = new SpelExpressionParser(); Expression expression1 = parser.parseExpression("list.?[ value>2 ].size()!=0"); @@ -1562,7 +1562,7 @@ public void SPR12035() { } @Test - public void SPR13055_maps() { + void SPR13055_maps() { EvaluationContext context = new StandardEvaluationContext(); ExpressionParser parser = new SpelExpressionParser(); @@ -1578,7 +1578,7 @@ public void SPR13055_maps() { @Test @SuppressWarnings({ "unchecked", "rawtypes" }) - public void SPR10417() { + void SPR10417() { List list1 = new ArrayList(); list1.add("a"); list1.add("b"); @@ -1619,7 +1619,7 @@ public void SPR10417() { @Test @SuppressWarnings({ "unchecked", "rawtypes" }) - public void SPR10417_maps() { + void SPR10417_maps() { Map map1 = new HashMap(); map1.put("A", 65); map1.put("B", 66); @@ -1642,7 +1642,7 @@ public void SPR10417_maps() { } @Test - public void SPR13918() { + void SPR13918() { EvaluationContext context = new StandardEvaluationContext(); context.setVariable("encoding", "UTF-8"); @@ -1652,7 +1652,7 @@ public void SPR13918() { } @Test - public void SPR16032() { + void SPR16032() { EvaluationContext context = new StandardEvaluationContext(); context.setVariable("str", "a\0b"); diff --git a/spring-jdbc/spring-jdbc.gradle b/spring-jdbc/spring-jdbc.gradle index e0737be91f53..41aa3f198720 100644 --- a/spring-jdbc/spring-jdbc.gradle +++ b/spring-jdbc/spring-jdbc.gradle @@ -3,9 +3,9 @@ description = "Spring JDBC" apply plugin: "kotlin" dependencies { - compile(project(":spring-beans")) - compile(project(":spring-core")) - compile(project(":spring-tx")) + api(project(":spring-beans")) + api(project(":spring-core")) + api(project(":spring-tx")) optional(project(":spring-context")) // for JndiDataSourceLookup optional("javax.transaction:javax.transaction-api") optional("org.hsqldb:hsqldb") @@ -14,6 +14,6 @@ dependencies { optional("org.apache.derby:derbyclient") optional("org.jetbrains.kotlin:kotlin-reflect") optional("org.jetbrains.kotlin:kotlin-stdlib") - testCompile(testFixtures(project(":spring-beans"))) - testCompile(testFixtures(project(":spring-core"))) + testImplementation(testFixtures(project(":spring-beans"))) + testImplementation(testFixtures(project(":spring-core"))) } diff --git a/spring-jms/spring-jms.gradle b/spring-jms/spring-jms.gradle index a447c97a8084..32485dff84ba 100644 --- a/spring-jms/spring-jms.gradle +++ b/spring-jms/spring-jms.gradle @@ -1,10 +1,10 @@ description = "Spring JMS" dependencies { - compile(project(":spring-beans")) - compile(project(":spring-core")) - compile(project(":spring-messaging")) - compile(project(":spring-tx")) + api(project(":spring-beans")) + api(project(":spring-core")) + api(project(":spring-messaging")) + api(project(":spring-tx")) compileOnly("javax.jms:javax.jms-api") optional(project(":spring-aop")) optional(project(":spring-context")) @@ -12,8 +12,8 @@ dependencies { optional("javax.resource:javax.resource-api") optional("javax.transaction:javax.transaction-api") optional("com.fasterxml.jackson.core:jackson-databind") - testCompile(testFixtures(project(":spring-beans"))) - testCompile(testFixtures(project(":spring-tx"))) - testCompile("org.apache.activemq:activemq-broker") + testImplementation(testFixtures(project(":spring-beans"))) + testImplementation(testFixtures(project(":spring-tx"))) + testImplementation("org.apache.activemq:activemq-broker") testImplementation("javax.jms:javax.jms-api") } diff --git a/spring-jms/src/main/java/org/springframework/jms/support/converter/MappingJackson2MessageConverter.java b/spring-jms/src/main/java/org/springframework/jms/support/converter/MappingJackson2MessageConverter.java index 819bbdb3f800..401f5c0cb5ed 100644 --- a/spring-jms/src/main/java/org/springframework/jms/support/converter/MappingJackson2MessageConverter.java +++ b/spring-jms/src/main/java/org/springframework/jms/support/converter/MappingJackson2MessageConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -92,6 +92,7 @@ public class MappingJackson2MessageConverter implements SmartMessageConverter, B private ClassLoader beanClassLoader; + @SuppressWarnings("deprecation") // on Jackson 2.13: configure(MapperFeature, boolean) public MappingJackson2MessageConverter() { this.objectMapper = new ObjectMapper(); this.objectMapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false); diff --git a/spring-jms/src/test/java/org/springframework/jms/listener/adapter/MessageListenerAdapterTests.java b/spring-jms/src/test/java/org/springframework/jms/listener/adapter/MessageListenerAdapterTests.java index f78a8d13fe3c..ceeab1c3b36a 100644 --- a/spring-jms/src/test/java/org/springframework/jms/listener/adapter/MessageListenerAdapterTests.java +++ b/spring-jms/src/test/java/org/springframework/jms/listener/adapter/MessageListenerAdapterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -32,7 +32,6 @@ import javax.jms.TextMessage; import org.junit.jupiter.api.Test; -import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.springframework.jms.support.converter.MessageConversionException; @@ -51,7 +50,7 @@ * @author Juergen Hoeller * @author Chris Beams */ -public class MessageListenerAdapterTests { +class MessageListenerAdapterTests { private static final String TEXT = "I fancy a good cuppa right now"; @@ -65,7 +64,7 @@ public class MessageListenerAdapterTests { @Test - public void testWithMessageContentsDelegateForTextMessage() throws Exception { + void testWithMessageContentsDelegateForTextMessage() throws Exception { TextMessage textMessage = mock(TextMessage.class); // TextMessage contents must be unwrapped... given(textMessage.getText()).willReturn(TEXT); @@ -79,17 +78,14 @@ public void testWithMessageContentsDelegateForTextMessage() throws Exception { } @Test - public void testWithMessageContentsDelegateForBytesMessage() throws Exception { + void testWithMessageContentsDelegateForBytesMessage() throws Exception { BytesMessage bytesMessage = mock(BytesMessage.class); // BytesMessage contents must be unwrapped... - given(bytesMessage.getBodyLength()).willReturn(new Long(TEXT.getBytes().length)); - given(bytesMessage.readBytes(any(byte[].class))).willAnswer(new Answer() { - @Override - public Integer answer(InvocationOnMock invocation) throws Throwable { - byte[] bytes = (byte[]) invocation.getArguments()[0]; - ByteArrayInputStream inputStream = new ByteArrayInputStream(TEXT.getBytes()); - return inputStream.read(bytes); - } + given(bytesMessage.getBodyLength()).willReturn(Long.valueOf(TEXT.getBytes().length)); + given(bytesMessage.readBytes(any(byte[].class))).willAnswer((Answer) invocation -> { + byte[] bytes = (byte[]) invocation.getArguments()[0]; + ByteArrayInputStream inputStream = new ByteArrayInputStream(TEXT.getBytes()); + return inputStream.read(bytes); }); MessageContentsDelegate delegate = mock(MessageContentsDelegate.class); @@ -101,7 +97,7 @@ public Integer answer(InvocationOnMock invocation) throws Throwable { } @Test - public void testWithMessageContentsDelegateForObjectMessage() throws Exception { + void testWithMessageContentsDelegateForObjectMessage() throws Exception { ObjectMessage objectMessage = mock(ObjectMessage.class); given(objectMessage.getObject()).willReturn(NUMBER); @@ -114,7 +110,7 @@ public void testWithMessageContentsDelegateForObjectMessage() throws Exception { } @Test - public void testWithMessageContentsDelegateForObjectMessageWithPlainObject() throws Exception { + void testWithMessageContentsDelegateForObjectMessageWithPlainObject() throws Exception { ObjectMessage objectMessage = mock(ObjectMessage.class); given(objectMessage.getObject()).willReturn(OBJECT); @@ -127,7 +123,7 @@ public void testWithMessageContentsDelegateForObjectMessageWithPlainObject() thr } @Test - public void testWithMessageDelegate() throws Exception { + void testWithMessageDelegate() throws Exception { TextMessage textMessage = mock(TextMessage.class); MessageDelegate delegate = mock(MessageDelegate.class); @@ -141,7 +137,7 @@ public void testWithMessageDelegate() throws Exception { } @Test - public void testWhenTheAdapterItselfIsTheDelegate() throws Exception { + void testWhenTheAdapterItselfIsTheDelegate() throws Exception { TextMessage textMessage = mock(TextMessage.class); // TextMessage contents must be unwrapped... given(textMessage.getText()).willReturn(TEXT); @@ -152,7 +148,7 @@ public void testWhenTheAdapterItselfIsTheDelegate() throws Exception { } @Test - public void testRainyDayWithNoApplicableHandlingMethods() throws Exception { + void testRainyDayWithNoApplicableHandlingMethods() throws Exception { TextMessage textMessage = mock(TextMessage.class); // TextMessage contents must be unwrapped... given(textMessage.getText()).willReturn(TEXT); @@ -164,7 +160,7 @@ public void testRainyDayWithNoApplicableHandlingMethods() throws Exception { } @Test - public void testThatAnExceptionThrownFromTheHandlingMethodIsSimplySwallowedByDefault() throws Exception { + void testThatAnExceptionThrownFromTheHandlingMethodIsSimplySwallowedByDefault() throws Exception { final IllegalArgumentException exception = new IllegalArgumentException(); TextMessage textMessage = mock(TextMessage.class); @@ -189,7 +185,7 @@ protected void handleListenerException(Throwable ex) { } @Test - public void testThatTheDefaultMessageConverterisIndeedTheSimpleMessageConverter() throws Exception { + void testThatTheDefaultMessageConverterisIndeedTheSimpleMessageConverter() throws Exception { MessageListenerAdapter adapter = new MessageListenerAdapter(); assertThat(adapter.getMessageConverter()).as("The default [MessageConverter] must never be null.").isNotNull(); boolean condition = adapter.getMessageConverter() instanceof SimpleMessageConverter; @@ -197,19 +193,19 @@ public void testThatTheDefaultMessageConverterisIndeedTheSimpleMessageConverter( } @Test - public void testThatWhenNoDelegateIsSuppliedTheDelegateIsAssumedToBeTheMessageListenerAdapterItself() throws Exception { + void testThatWhenNoDelegateIsSuppliedTheDelegateIsAssumedToBeTheMessageListenerAdapterItself() throws Exception { MessageListenerAdapter adapter = new MessageListenerAdapter(); assertThat(adapter.getDelegate()).isSameAs(adapter); } @Test - public void testThatTheDefaultMessageHandlingMethodNameIsTheConstantDefault() throws Exception { + void testThatTheDefaultMessageHandlingMethodNameIsTheConstantDefault() throws Exception { MessageListenerAdapter adapter = new MessageListenerAdapter(); assertThat(adapter.getDefaultListenerMethod()).isEqualTo(MessageListenerAdapter.ORIGINAL_DEFAULT_LISTENER_METHOD); } @Test - public void testWithResponsiveMessageDelegate_DoesNotSendReturnTextMessageIfNoSessionSupplied() throws Exception { + void testWithResponsiveMessageDelegate_DoesNotSendReturnTextMessageIfNoSessionSupplied() throws Exception { TextMessage textMessage = mock(TextMessage.class); ResponsiveMessageDelegate delegate = mock(ResponsiveMessageDelegate.class); given(delegate.handleMessage(textMessage)).willReturn(TEXT); @@ -221,7 +217,7 @@ public void testWithResponsiveMessageDelegate_DoesNotSendReturnTextMessageIfNoSe } @Test - public void testWithResponsiveMessageDelegateWithDefaultDestination_SendsReturnTextMessageWhenSessionSupplied() throws Exception { + void testWithResponsiveMessageDelegateWithDefaultDestination_SendsReturnTextMessageWhenSessionSupplied() throws Exception { Queue destination = mock(Queue.class); TextMessage sentTextMessage = mock(TextMessage.class); // correlation ID is queried when response is being created... @@ -256,7 +252,7 @@ protected Object extractMessage(Message message) { } @Test - public void testWithResponsiveMessageDelegateNoDefaultDestination_SendsReturnTextMessageWhenSessionSupplied() throws Exception { + void testWithResponsiveMessageDelegateNoDefaultDestination_SendsReturnTextMessageWhenSessionSupplied() throws Exception { Queue destination = mock(Queue.class); TextMessage sentTextMessage = mock(TextMessage.class); // correlation ID is queried when response is being created... @@ -289,7 +285,7 @@ protected Object extractMessage(Message message) { } @Test - public void testWithResponsiveMessageDelegateNoDefaultDestinationAndNoReplyToDestination_SendsReturnTextMessageWhenSessionSupplied() throws Exception { + void testWithResponsiveMessageDelegateNoDefaultDestinationAndNoReplyToDestination_SendsReturnTextMessageWhenSessionSupplied() throws Exception { final TextMessage sentTextMessage = mock(TextMessage.class); // correlation ID is queried when response is being created... given(sentTextMessage.getJMSCorrelationID()).willReturn(CORRELATION_ID); @@ -318,7 +314,7 @@ protected Object extractMessage(Message message) { } @Test - public void testWithResponsiveMessageDelegateNoDefaultDestination_SendsReturnTextMessageWhenSessionSupplied_AndSendingThrowsJMSException() throws Exception { + void testWithResponsiveMessageDelegateNoDefaultDestination_SendsReturnTextMessageWhenSessionSupplied_AndSendingThrowsJMSException() throws Exception { Queue destination = mock(Queue.class); final TextMessage sentTextMessage = mock(TextMessage.class); @@ -354,7 +350,7 @@ protected Object extractMessage(Message message) { } @Test - public void testWithResponsiveMessageDelegateDoesNotSendReturnTextMessageWhenSessionSupplied_AndListenerMethodThrowsException() throws Exception { + void testWithResponsiveMessageDelegateDoesNotSendReturnTextMessageWhenSessionSupplied_AndListenerMethodThrowsException() throws Exception { final TextMessage message = mock(TextMessage.class); final QueueSession session = mock(QueueSession.class); @@ -372,7 +368,7 @@ protected Object extractMessage(Message message) { } @Test - public void testWithResponsiveMessageDelegateWhenReturnTypeIsNotAJMSMessageAndNoMessageConverterIsSupplied() throws Exception { + void testWithResponsiveMessageDelegateWhenReturnTypeIsNotAJMSMessageAndNoMessageConverterIsSupplied() throws Exception { final TextMessage sentTextMessage = mock(TextMessage.class); final Session session = mock(Session.class); ResponsiveMessageDelegate delegate = mock(ResponsiveMessageDelegate.class); @@ -391,7 +387,7 @@ protected Object extractMessage(Message message) { } @Test - public void testWithResponsiveMessageDelegateWhenReturnTypeIsAJMSMessageAndNoMessageConverterIsSupplied() throws Exception { + void testWithResponsiveMessageDelegateWhenReturnTypeIsAJMSMessageAndNoMessageConverterIsSupplied() throws Exception { Queue destination = mock(Queue.class); final TextMessage sentTextMessage = mock(TextMessage.class); // correlation ID is queried when response is being created... diff --git a/spring-jms/src/test/java/org/springframework/jms/support/converter/MappingJackson2MessageConverterTests.java b/spring-jms/src/test/java/org/springframework/jms/support/converter/MappingJackson2MessageConverterTests.java index a7942cccb8e0..4f428c270939 100644 --- a/spring-jms/src/test/java/org/springframework/jms/support/converter/MappingJackson2MessageConverterTests.java +++ b/spring-jms/src/test/java/org/springframework/jms/support/converter/MappingJackson2MessageConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -31,7 +31,6 @@ import com.fasterxml.jackson.annotation.JsonView; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.springframework.core.MethodParameter; @@ -49,7 +48,7 @@ * @author Dave Syer * @author Stephane Nicoll */ -public class MappingJackson2MessageConverterTests { +class MappingJackson2MessageConverterTests { private MappingJackson2MessageConverter converter; @@ -66,7 +65,7 @@ public void setup() { @Test - public void toBytesMessage() throws Exception { + void toBytesMessage() throws Exception { BytesMessage bytesMessageMock = mock(BytesMessage.class); Date toBeMarshalled = new Date(); @@ -80,7 +79,7 @@ public void toBytesMessage() throws Exception { } @Test - public void fromBytesMessage() throws Exception { + void fromBytesMessage() throws Exception { BytesMessage bytesMessageMock = mock(BytesMessage.class); Map unmarshalled = Collections.singletonMap("foo", "bar"); @@ -89,21 +88,16 @@ public void fromBytesMessage() throws Exception { given(bytesMessageMock.getStringProperty("__typeid__")).willReturn(Object.class.getName()); given(bytesMessageMock.propertyExists("__encoding__")).willReturn(false); - given(bytesMessageMock.getBodyLength()).willReturn(new Long(bytes.length)); + given(bytesMessageMock.getBodyLength()).willReturn(Long.valueOf(bytes.length)); given(bytesMessageMock.readBytes(any(byte[].class))).willAnswer( - new Answer() { - @Override - public Integer answer(InvocationOnMock invocation) throws Throwable { - return byteStream.read((byte[]) invocation.getArguments()[0]); - } - }); + (Answer) invocation -> byteStream.read((byte[]) invocation.getArguments()[0])); Object result = converter.fromMessage(bytesMessageMock); assertThat(unmarshalled).as("Invalid result").isEqualTo(result); } @Test - public void toTextMessageWithObject() throws Exception { + void toTextMessageWithObject() throws Exception { converter.setTargetType(MessageType.TEXT); TextMessage textMessageMock = mock(TextMessage.class); Date toBeMarshalled = new Date(); @@ -115,7 +109,7 @@ public void toTextMessageWithObject() throws Exception { } @Test - public void toTextMessageWithMap() throws Exception { + void toTextMessageWithMap() throws Exception { converter.setTargetType(MessageType.TEXT); TextMessage textMessageMock = mock(TextMessage.class); Map toBeMarshalled = new HashMap<>(); @@ -128,7 +122,7 @@ public void toTextMessageWithMap() throws Exception { } @Test - public void fromTextMessage() throws Exception { + void fromTextMessage() throws Exception { TextMessage textMessageMock = mock(TextMessage.class); MyBean unmarshalled = new MyBean("bar"); @@ -141,7 +135,7 @@ public void fromTextMessage() throws Exception { } @Test - public void fromTextMessageWithUnknownProperty() throws Exception { + void fromTextMessageWithUnknownProperty() throws Exception { TextMessage textMessageMock = mock(TextMessage.class); MyBean unmarshalled = new MyBean("bar"); @@ -154,7 +148,7 @@ public void fromTextMessageWithUnknownProperty() throws Exception { } @Test - public void fromTextMessageAsObject() throws Exception { + void fromTextMessageAsObject() throws Exception { TextMessage textMessageMock = mock(TextMessage.class); Map unmarshalled = Collections.singletonMap("foo", "bar"); @@ -167,7 +161,7 @@ public void fromTextMessageAsObject() throws Exception { } @Test - public void fromTextMessageAsMap() throws Exception { + void fromTextMessageAsMap() throws Exception { TextMessage textMessageMock = mock(TextMessage.class); Map unmarshalled = Collections.singletonMap("foo", "bar"); @@ -180,7 +174,7 @@ public void fromTextMessageAsMap() throws Exception { } @Test - public void toTextMessageWithReturnType() throws JMSException, NoSuchMethodException { + void toTextMessageWithReturnType() throws JMSException, NoSuchMethodException { Method method = this.getClass().getDeclaredMethod("summary"); MethodParameter returnType = new MethodParameter(method, -1); testToTextMessageWithReturnType(returnType); @@ -188,13 +182,13 @@ public void toTextMessageWithReturnType() throws JMSException, NoSuchMethodExcep } @Test - public void toTextMessageWithNullReturnType() throws JMSException, NoSuchMethodException { + void toTextMessageWithNullReturnType() throws JMSException, NoSuchMethodException { testToTextMessageWithReturnType(null); verify(sessionMock).createTextMessage("{\"name\":\"test\",\"description\":\"lengthy description\"}"); } @Test - public void toTextMessageWithReturnTypeAndNoJsonView() throws JMSException, NoSuchMethodException { + void toTextMessageWithReturnTypeAndNoJsonView() throws JMSException, NoSuchMethodException { Method method = this.getClass().getDeclaredMethod("none"); MethodParameter returnType = new MethodParameter(method, -1); @@ -203,7 +197,7 @@ public void toTextMessageWithReturnTypeAndNoJsonView() throws JMSException, NoSu } @Test - public void toTextMessageWithReturnTypeAndMultipleJsonViews() throws JMSException, NoSuchMethodException { + void toTextMessageWithReturnTypeAndMultipleJsonViews() throws JMSException, NoSuchMethodException { Method method = this.getClass().getDeclaredMethod("invalid"); MethodParameter returnType = new MethodParameter(method, -1); @@ -222,7 +216,7 @@ private void testToTextMessageWithReturnType(MethodParameter returnType) throws } @Test - public void toTextMessageWithJsonViewClass() throws JMSException { + void toTextMessageWithJsonViewClass() throws JMSException { converter.setTargetType(MessageType.TEXT); TextMessage textMessageMock = mock(TextMessage.class); @@ -236,7 +230,7 @@ public void toTextMessageWithJsonViewClass() throws JMSException { } @Test - public void toTextMessageWithAnotherJsonViewClass() throws JMSException { + void toTextMessageWithAnotherJsonViewClass() throws JMSException { converter.setTargetType(MessageType.TEXT); TextMessage textMessageMock = mock(TextMessage.class); diff --git a/spring-messaging/spring-messaging.gradle b/spring-messaging/spring-messaging.gradle index 2973da314984..c0c7270ebde2 100644 --- a/spring-messaging/spring-messaging.gradle +++ b/spring-messaging/spring-messaging.gradle @@ -4,9 +4,8 @@ apply plugin: "kotlin" apply plugin: "kotlinx-serialization" dependencies { - compile(project(":spring-beans")) - compile(project(":spring-core")) - compileOnly(project(":kotlin-coroutines")) + api(project(":spring-beans")) + api(project(":spring-core")) optional(project(":spring-context")) optional(project(":spring-oxm")) optional("io.projectreactor.netty:reactor-netty-http") @@ -19,25 +18,24 @@ dependencies { optional("com.google.protobuf:protobuf-java-util") optional("org.jetbrains.kotlinx:kotlinx-coroutines-reactor") optional("org.jetbrains.kotlinx:kotlinx-serialization-json") - testCompile(project(":kotlin-coroutines")) - testCompile(testFixtures(project(":spring-core"))) - testCompile("javax.inject:javax.inject-tck") - testCompile("javax.servlet:javax.servlet-api") - testCompile("javax.validation:validation-api") - testCompile("com.thoughtworks.xstream:xstream") - testCompile("org.apache.activemq:activemq-broker") - testCompile("org.apache.activemq:activemq-kahadb-store") - testCompile("org.apache.activemq:activemq-stomp") - testCompile("io.projectreactor:reactor-test") - testCompile "io.reactivex.rxjava3:rxjava" - testCompile("org.jetbrains.kotlin:kotlin-reflect") - testCompile("org.jetbrains.kotlin:kotlin-stdlib") - testCompile("org.xmlunit:xmlunit-assertj") - testCompile("org.xmlunit:xmlunit-matchers") - testRuntime("com.sun.activation:javax.activation") - testRuntime("com.sun.xml.bind:jaxb-core") - testRuntime("com.sun.xml.bind:jaxb-impl") - testRuntime("javax.json:javax.json-api") - testRuntime("org.apache.johnzon:johnzon-jsonb") - testRuntime(project(":spring-context")) + testImplementation(testFixtures(project(":spring-core"))) + testImplementation("javax.inject:javax.inject-tck") + testImplementation("javax.servlet:javax.servlet-api") + testImplementation("javax.validation:validation-api") + testImplementation("com.thoughtworks.xstream:xstream") + testImplementation("org.apache.activemq:activemq-broker") + testImplementation("org.apache.activemq:activemq-kahadb-store") + testImplementation("org.apache.activemq:activemq-stomp") + testImplementation("io.projectreactor:reactor-test") + testImplementation("io.reactivex.rxjava3:rxjava") + testImplementation("org.jetbrains.kotlin:kotlin-reflect") + testImplementation("org.jetbrains.kotlin:kotlin-stdlib") + testImplementation("org.xmlunit:xmlunit-assertj") + testImplementation("org.xmlunit:xmlunit-matchers") + testRuntimeOnly("com.sun.activation:javax.activation") + testRuntimeOnly("com.sun.xml.bind:jaxb-core") + testRuntimeOnly("com.sun.xml.bind:jaxb-impl") + testRuntimeOnly("javax.json:javax.json-api") + testRuntimeOnly("org.apache.johnzon:johnzon-jsonb") + testRuntimeOnly(project(":spring-context")) } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/converter/MappingJackson2MessageConverter.java b/spring-messaging/src/main/java/org/springframework/messaging/converter/MappingJackson2MessageConverter.java index 349b07ad19db..9bb32eebd942 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/converter/MappingJackson2MessageConverter.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/converter/MappingJackson2MessageConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -88,6 +88,7 @@ public MappingJackson2MessageConverter(MimeType... supportedMimeTypes) { } + @SuppressWarnings("deprecation") // on Jackson 2.13: configure(MapperFeature, boolean) private ObjectMapper initObjectMapper() { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false); diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/HandlerMethod.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/HandlerMethod.java index 496266b1089d..4ace844929fb 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/HandlerMethod.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/HandlerMethod.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -33,6 +33,7 @@ import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; +import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; /** @@ -87,6 +88,7 @@ public HandlerMethod(Object bean, Method method) { this.beanType = ClassUtils.getUserClass(bean); this.method = method; this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); + ReflectionUtils.makeAccessible(this.bridgedMethod); this.parameters = initMethodParameters(); } @@ -102,6 +104,7 @@ public HandlerMethod(Object bean, String methodName, Class... parameterTypes) this.beanType = ClassUtils.getUserClass(bean); this.method = bean.getClass().getMethod(methodName, parameterTypes); this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(this.method); + ReflectionUtils.makeAccessible(this.bridgedMethod); this.parameters = initMethodParameters(); } @@ -123,6 +126,7 @@ public HandlerMethod(String beanName, BeanFactory beanFactory, Method method) { this.beanType = ClassUtils.getUserClass(beanType); this.method = method; this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); + ReflectionUtils.makeAccessible(this.bridgedMethod); this.parameters = initMethodParameters(); } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/AbstractMethodMessageHandler.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/AbstractMethodMessageHandler.java index fc50155039c4..f160d506eed7 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/AbstractMethodMessageHandler.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/AbstractMethodMessageHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -53,6 +53,7 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; +import org.springframework.util.StringUtils; import org.springframework.util.concurrent.ListenableFuture; import org.springframework.util.concurrent.ListenableFutureCallback; @@ -319,9 +320,12 @@ protected final void detectHandlerMethods(final Object handler) { } private String formatMappings(Class userType, Map methods) { - String formattedType = Arrays.stream(ClassUtils.getPackageName(userType).split("\\.")) - .map(p -> p.substring(0, 1)) - .collect(Collectors.joining(".", "", "." + userType.getSimpleName())); + String packageName = ClassUtils.getPackageName(userType); + String formattedType = (StringUtils.hasText(packageName) ? + Arrays.stream(packageName.split("\\.")) + .map(packageSegment -> packageSegment.substring(0, 1)) + .collect(Collectors.joining(".", "", "." + userType.getSimpleName())) : + userType.getSimpleName()); Function methodFormatter = method -> Arrays.stream(method.getParameterTypes()) .map(Class::getSimpleName) .collect(Collectors.joining(",", "(", ")")); diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java index b9430fdb9aa6..3dc5e2ec2630 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -29,7 +29,6 @@ import org.springframework.messaging.Message; import org.springframework.messaging.handler.HandlerMethod; import org.springframework.util.ObjectUtils; -import org.springframework.util.ReflectionUtils; /** * Extension of {@link HandlerMethod} that invokes the underlying method with @@ -166,7 +165,6 @@ protected Object[] getMethodArgumentValues(Message message, Object... provide */ @Nullable protected Object doInvoke(Object... args) throws Exception { - ReflectionUtils.makeAccessible(getBridgedMethod()); try { return getBridgedMethod().invoke(getBean(), args); } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/AbstractMethodMessageHandler.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/AbstractMethodMessageHandler.java index 1d85930585cb..a240f4d8efa0 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/AbstractMethodMessageHandler.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/AbstractMethodMessageHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -54,6 +54,7 @@ import org.springframework.util.MultiValueMap; import org.springframework.util.ObjectUtils; import org.springframework.util.RouteMatcher; +import org.springframework.util.StringUtils; /** * Abstract base class for reactive HandlerMethod-based message handling. @@ -341,9 +342,12 @@ protected final void detectHandlerMethods(Object handler) { } private String formatMappings(Class userType, Map methods) { - String formattedType = Arrays.stream(ClassUtils.getPackageName(userType).split("\\.")) - .map(p -> p.substring(0, 1)) - .collect(Collectors.joining(".", "", "." + userType.getSimpleName())); + String packageName = ClassUtils.getPackageName(userType); + String formattedType = (StringUtils.hasText(packageName) ? + Arrays.stream(packageName.split("\\.")) + .map(packageSegment -> packageSegment.substring(0, 1)) + .collect(Collectors.joining(".", "", "." + userType.getSimpleName())) : + userType.getSimpleName()); Function methodFormatter = method -> Arrays.stream(method.getParameterTypes()) .map(Class::getSimpleName) .collect(Collectors.joining(",", "(", ")")); diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/InvocableHandlerMethod.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/InvocableHandlerMethod.java index d4dfe1530683..aad9384af251 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/InvocableHandlerMethod.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/reactive/InvocableHandlerMethod.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -38,7 +38,6 @@ import org.springframework.messaging.handler.HandlerMethod; import org.springframework.messaging.handler.invocation.MethodArgumentResolutionException; import org.springframework.util.ObjectUtils; -import org.springframework.util.ReflectionUtils; /** * Extension of {@link HandlerMethod} that invokes the underlying method with @@ -130,7 +129,6 @@ public Mono invoke(Message message, Object... providedArgs) { boolean isSuspendingFunction = false; try { Method method = getBridgedMethod(); - ReflectionUtils.makeAccessible(method); if (KotlinDetector.isSuspendingFunction(method)) { isSuspendingFunction = true; value = CoroutinesUtils.invokeSuspendingFunction(method, getBean(), args); diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/config/AbstractMessageBrokerConfiguration.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/config/AbstractMessageBrokerConfiguration.java index df9b5320fb1f..fb4150ad7b0e 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/config/AbstractMessageBrokerConfiguration.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/config/AbstractMessageBrokerConfiguration.java @@ -83,7 +83,7 @@ * * *

    {@link #brokerChannel} delivers messages from within the application to the - * the respective message handlers. {@link #brokerMessagingTemplate} can be injected + * respective message handlers. {@link #brokerMessagingTemplate} can be injected * into any application component to send messages. * *

    Subclasses are responsible for the parts of the configuration that feed messages diff --git a/spring-orm/spring-orm.gradle b/spring-orm/spring-orm.gradle index 8a8ad57ac4c3..7870f5d77d72 100644 --- a/spring-orm/spring-orm.gradle +++ b/spring-orm/spring-orm.gradle @@ -1,21 +1,21 @@ description = "Spring Object/Relational Mapping" dependencies { - compile(project(":spring-beans")) - compile(project(":spring-core")) - compile(project(":spring-jdbc")) - compile(project(":spring-tx")) + api(project(":spring-beans")) + api(project(":spring-core")) + api(project(":spring-jdbc")) + api(project(":spring-tx")) optional(project(":spring-aop")) optional(project(":spring-context")) optional(project(":spring-web")) optional("org.eclipse.persistence:org.eclipse.persistence.jpa") optional("org.hibernate:hibernate-core") - optional("javax.servlet:javax.servlet-api:3.1.0") - testCompile(testFixtures(project(":spring-beans"))) - testCompile(testFixtures(project(":spring-context"))) - testCompile(testFixtures(project(":spring-core"))) - testCompile(testFixtures(project(":spring-web"))) - testCompile("org.aspectj:aspectjweaver") - testCompile("org.hsqldb:hsqldb") - testRuntime("javax.xml.bind:jaxb-api") + optional("javax.servlet:javax.servlet-api") + testImplementation(testFixtures(project(":spring-beans"))) + testImplementation(testFixtures(project(":spring-context"))) + testImplementation(testFixtures(project(":spring-core"))) + testImplementation(testFixtures(project(":spring-web"))) + testImplementation("org.aspectj:aspectjweaver") + testImplementation("org.hsqldb:hsqldb") + testRuntimeOnly("javax.xml.bind:jaxb-api") } diff --git a/spring-oxm/spring-oxm.gradle b/spring-oxm/spring-oxm.gradle index 901c4ba072b4..f47726a8bd5b 100644 --- a/spring-oxm/spring-oxm.gradle +++ b/spring-oxm/spring-oxm.gradle @@ -16,6 +16,7 @@ dependencies { xjc { xjcVersion = '2.2' } + sourceSets { test { xjcTargetPackage = 'org.springframework.oxm.jaxb.test' @@ -23,23 +24,23 @@ sourceSets { } dependencies { - compile(project(":spring-beans")) - compile(project(":spring-core")) + api(project(":spring-beans")) + api(project(":spring-core")) optional("javax.xml.bind:jaxb-api") optional("javax.activation:javax.activation-api") optional("com.thoughtworks.xstream:xstream") optional("org.jibx:jibx-run") - testCompile(project(":spring-context")) - testCompile(testFixtures(project(":spring-core"))) - testCompile("org.ogce:xpp3") - testCompile("org.codehaus.jettison:jettison") { + testImplementation(project(":spring-context")) + testImplementation(testFixtures(project(":spring-core"))) + testImplementation("org.ogce:xpp3") + testImplementation("org.codehaus.jettison:jettison") { exclude group: "stax", module: "stax-api" } - //testCompile(files(genJaxb.classesDir).builtBy(genJaxb)) - testCompile("org.xmlunit:xmlunit-assertj") - testCompile("org.xmlunit:xmlunit-matchers") - testRuntime("com.sun.xml.bind:jaxb-core") - testRuntime("com.sun.xml.bind:jaxb-impl") + //testImplementation(files(genJaxb.classesDir).builtBy(genJaxb)) + testImplementation("org.xmlunit:xmlunit-assertj") + testImplementation("org.xmlunit:xmlunit-matchers") + testRuntimeOnly("com.sun.xml.bind:jaxb-core") + testRuntimeOnly("com.sun.xml.bind:jaxb-impl") } // JiBX compiler is currently not compatible with JDK 9+. @@ -55,7 +56,7 @@ if ((JavaVersion.current() == JavaVersion.VERSION_1_8) && !project.hasProperty(" classpath: configurations.jibx.asPath) jibx(verbose: false, load: true, binding: bindingXml) { - classpathset(dir: sourceSets.test.java.outputDir) { + classpathset(dir: sourceSets.test.java.classesDirectory.get().getAsFile()) { include(name: "**/jibx/**/*") } } diff --git a/spring-oxm/src/main/java/org/springframework/oxm/xstream/XStreamMarshaller.java b/spring-oxm/src/main/java/org/springframework/oxm/xstream/XStreamMarshaller.java index a992ab814188..ccb10d27c172 100644 --- a/spring-oxm/src/main/java/org/springframework/oxm/xstream/XStreamMarshaller.java +++ b/spring-oxm/src/main/java/org/springframework/oxm/xstream/XStreamMarshaller.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -63,6 +63,8 @@ import com.thoughtworks.xstream.mapper.CannotResolveClassException; import com.thoughtworks.xstream.mapper.Mapper; import com.thoughtworks.xstream.mapper.MapperWrapper; +import com.thoughtworks.xstream.security.ForbiddenClassException; +import com.thoughtworks.xstream.security.TypePermission; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -106,7 +108,7 @@ * Therefore, it has limited namespace support. As such, it is rather unsuitable for * usage within Web Services. * - *

    This marshaller requires XStream 1.4.5 or higher, as of Spring 4.3. + *

    This marshaller requires XStream 1.4.7 or higher, as of Spring 5.2.17. * Note that {@link XStream} construction has been reworked in 4.0, with the * stream driver and the class loader getting passed into XStream itself now. * @@ -146,6 +148,9 @@ public class XStreamMarshaller extends AbstractMarshaller implements BeanClassLo @Nullable private ConverterMatcher[] converters; + @Nullable + private TypePermission[] typePermissions; + @Nullable private MarshallingStrategy marshallingStrategy; @@ -268,6 +273,20 @@ public void setConverters(ConverterMatcher... converters) { this.converters = converters; } + /** + * Set XStream type permissions such as + * {@link com.thoughtworks.xstream.security.AnyTypePermission}, + * {@link com.thoughtworks.xstream.security.ExplicitTypePermission} etc, + * as an alternative to overriding the {@link #customizeXStream} method. + *

    Note: As of XStream 1.4.18, the default type permissions are + * restricted to well-known core JDK types. For any custom types, + * explicit type permissions need to be registered. + * @since 5.2.17 + */ + public void setTypePermissions(TypePermission... typePermissions) { + this.typePermissions = typePermissions; + } + /** * Set a custom XStream {@link MarshallingStrategy} to use. * @since 4.0 @@ -407,7 +426,7 @@ public void setBeanClassLoader(ClassLoader classLoader) { @Override public void afterPropertiesSet() { - // no-op due to use of SingletonSupplier for the XStream field. + // no-op due to use of SingletonSupplier for the XStream field } /** @@ -479,6 +498,12 @@ else if (this.converters[i] instanceof SingleValueConverter) { } } + if (this.typePermissions != null) { + for (TypePermission permission : this.typePermissions) { + xstream.addPermission(permission); + } + } + if (this.marshallingStrategy != null) { xstream.setMarshallingStrategy(this.marshallingStrategy); } @@ -844,7 +869,7 @@ private Object doUnmarshal(HierarchicalStreamReader streamReader, @Nullable Data */ protected XmlMappingException convertXStreamException(Exception ex, boolean marshalling) { if (ex instanceof StreamException || ex instanceof CannotResolveClassException || - ex instanceof ConversionException) { + ex instanceof ForbiddenClassException || ex instanceof ConversionException) { if (marshalling) { return new MarshallingFailureException("XStream marshalling exception", ex); } diff --git a/spring-oxm/src/test/java/org/springframework/oxm/xstream/XStreamMarshallerTests.java b/spring-oxm/src/test/java/org/springframework/oxm/xstream/XStreamMarshallerTests.java index 5f05936d751a..304d3fcc771b 100644 --- a/spring-oxm/src/test/java/org/springframework/oxm/xstream/XStreamMarshallerTests.java +++ b/spring-oxm/src/test/java/org/springframework/oxm/xstream/XStreamMarshallerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -43,6 +43,7 @@ import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver; import com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver; import com.thoughtworks.xstream.io.json.JsonWriter; +import com.thoughtworks.xstream.security.AnyTypePermission; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.InOrder; @@ -67,18 +68,21 @@ /** * @author Arjen Poutsma * @author Sam Brannen + * @author Juergen Hoeller */ class XStreamMarshallerTests { private static final String EXPECTED_STRING = "42"; - private final XStreamMarshaller marshaller = new XStreamMarshaller(); - private final Flight flight = new Flight(); + private XStreamMarshaller marshaller; + @BeforeEach void createMarshaller() { + marshaller = new XStreamMarshaller(); + marshaller.setTypePermissions(AnyTypePermission.ANY); marshaller.setAliases(Collections.singletonMap("flight", Flight.class.getName())); flight.setFlightNumber(42L); } @@ -143,7 +147,7 @@ void marshalStreamResultOutputStream() throws Exception { ByteArrayOutputStream os = new ByteArrayOutputStream(); StreamResult result = new StreamResult(os); marshaller.marshal(flight, result); - String s = new String(os.toByteArray(), "UTF-8"); + String s = os.toString("UTF-8"); assertThat(XmlContent.of(s)).isSimilarTo(EXPECTED_STRING); } diff --git a/spring-oxm/src/test/java/org/springframework/oxm/xstream/XStreamUnmarshallerTests.java b/spring-oxm/src/test/java/org/springframework/oxm/xstream/XStreamUnmarshallerTests.java index 1c864545aa68..7c87eda2253b 100644 --- a/spring-oxm/src/test/java/org/springframework/oxm/xstream/XStreamUnmarshallerTests.java +++ b/spring-oxm/src/test/java/org/springframework/oxm/xstream/XStreamUnmarshallerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -18,6 +18,7 @@ import java.io.ByteArrayInputStream; import java.io.StringReader; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; @@ -29,6 +30,7 @@ import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamSource; +import com.thoughtworks.xstream.security.AnyTypePermission; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.w3c.dom.Document; @@ -40,6 +42,7 @@ /** * @author Arjen Poutsma + * @author Juergen Hoeller */ public class XStreamUnmarshallerTests { @@ -47,21 +50,16 @@ public class XStreamUnmarshallerTests { private XStreamMarshaller unmarshaller; + @BeforeEach - public void createUnmarshaller() throws Exception { + public void createUnmarshaller() { unmarshaller = new XStreamMarshaller(); + unmarshaller.setTypePermissions(AnyTypePermission.ANY); Map> aliases = new HashMap<>(); aliases.put("flight", Flight.class); unmarshaller.setAliases(aliases); } - private void testFlight(Object o) { - boolean condition = o instanceof Flight; - assertThat(condition).as("Unmarshalled object is not Flights").isTrue(); - Flight flight = (Flight) o; - assertThat(flight).as("Flight is null").isNotNull(); - assertThat(flight.getFlightNumber()).as("Number is invalid").isEqualTo(42L); - } @Test public void unmarshalDomSource() throws Exception { @@ -83,7 +81,7 @@ public void unmarshalStaxSourceXmlStreamReader() throws Exception { @Test public void unmarshalStreamSourceInputStream() throws Exception { - StreamSource source = new StreamSource(new ByteArrayInputStream(INPUT_STRING.getBytes("UTF-8"))); + StreamSource source = new StreamSource(new ByteArrayInputStream(INPUT_STRING.getBytes(StandardCharsets.UTF_8))); Object flights = unmarshaller.unmarshal(source); testFlight(flights); } @@ -94,5 +92,15 @@ public void unmarshalStreamSourceReader() throws Exception { Object flights = unmarshaller.unmarshal(source); testFlight(flights); } + + + private void testFlight(Object o) { + boolean condition = o instanceof Flight; + assertThat(condition).as("Unmarshalled object is not Flights").isTrue(); + Flight flight = (Flight) o; + assertThat(flight).as("Flight is null").isNotNull(); + assertThat(flight.getFlightNumber()).as("Number is invalid").isEqualTo(42L); + } + } diff --git a/spring-r2dbc/spring-r2dbc.gradle b/spring-r2dbc/spring-r2dbc.gradle index 8fd50bf2e780..dfb6b1ece9d6 100644 --- a/spring-r2dbc/spring-r2dbc.gradle +++ b/spring-r2dbc/spring-r2dbc.gradle @@ -3,23 +3,21 @@ description = "Spring R2DBC" apply plugin: "kotlin" dependencies { - compile(project(":spring-beans")) - compile(project(":spring-core")) - compile(project(":spring-tx")) - compile("io.r2dbc:r2dbc-spi") - compile("io.projectreactor:reactor-core") - compileOnly(project(":kotlin-coroutines")) + api(project(":spring-beans")) + api(project(":spring-core")) + api(project(":spring-tx")) + api("io.r2dbc:r2dbc-spi") + api("io.projectreactor:reactor-core") optional("org.jetbrains.kotlin:kotlin-reflect") optional("org.jetbrains.kotlin:kotlin-stdlib") optional("org.jetbrains.kotlinx:kotlinx-coroutines-core") optional("org.jetbrains.kotlinx:kotlinx-coroutines-reactor") - testCompile(project(":kotlin-coroutines")) - testCompile(testFixtures(project(":spring-beans"))) - testCompile(testFixtures(project(":spring-core"))) - testCompile(testFixtures(project(":spring-context"))) - testCompile("io.projectreactor:reactor-test") - testCompile("io.r2dbc:r2dbc-h2") - testCompile("io.r2dbc:r2dbc-spi-test:0.8.1.RELEASE") { + testImplementation(testFixtures(project(":spring-beans"))) + testImplementation(testFixtures(project(":spring-core"))) + testImplementation(testFixtures(project(":spring-context"))) + testImplementation("io.projectreactor:reactor-test") + testImplementation("io.r2dbc:r2dbc-h2") + testImplementation("io.r2dbc:r2dbc-spi-test:0.8.1.RELEASE") { exclude group: "org.springframework", module: "spring-jdbc" } } diff --git a/spring-r2dbc/src/test/java/org/springframework/r2dbc/core/AbstractDatabaseClientIntegrationTests.java b/spring-r2dbc/src/test/java/org/springframework/r2dbc/core/AbstractDatabaseClientIntegrationTests.java index dff746cd59e6..d315a10290ac 100644 --- a/spring-r2dbc/src/test/java/org/springframework/r2dbc/core/AbstractDatabaseClientIntegrationTests.java +++ b/spring-r2dbc/src/test/java/org/springframework/r2dbc/core/AbstractDatabaseClientIntegrationTests.java @@ -59,7 +59,7 @@ public void before() { protected abstract ConnectionFactory createConnectionFactory(); /** - * Return the the CREATE TABLE statement for table {@code legoset} with the following + * Return the CREATE TABLE statement for table {@code legoset} with the following * three columns: *

      *
    • id integer (primary key), not null
    • diff --git a/spring-r2dbc/src/test/java/org/springframework/r2dbc/core/AbstractTransactionalDatabaseClientIntegrationTests.java b/spring-r2dbc/src/test/java/org/springframework/r2dbc/core/AbstractTransactionalDatabaseClientIntegrationTests.java index 1d90bc7a45cd..acebde10d4a2 100644 --- a/spring-r2dbc/src/test/java/org/springframework/r2dbc/core/AbstractTransactionalDatabaseClientIntegrationTests.java +++ b/spring-r2dbc/src/test/java/org/springframework/r2dbc/core/AbstractTransactionalDatabaseClientIntegrationTests.java @@ -89,7 +89,7 @@ public void tearDown() { protected abstract ConnectionFactory createConnectionFactory(); /** - * Return the the CREATE TABLE statement for table {@code legoset} with the following three columns: + * Return the CREATE TABLE statement for table {@code legoset} with the following three columns: *
        *
      • id integer (primary key), not null
      • *
      • name varchar(255), nullable
      • diff --git a/spring-test/spring-test.gradle b/spring-test/spring-test.gradle index 1223fdff57a9..365ce7d316f9 100644 --- a/spring-test/spring-test.gradle +++ b/spring-test/spring-test.gradle @@ -3,7 +3,7 @@ description = "Spring TestContext Framework" apply plugin: "kotlin" dependencies { - compile(project(":spring-core")) + api(project(":spring-core")) optional(project(":spring-aop")) optional(project(":spring-beans")) optional(project(":spring-context")) @@ -30,8 +30,12 @@ dependencies { optional("org.hamcrest:hamcrest") optional("org.apache.taglibs:taglibs-standard-jstlel") optional("net.sourceforge.htmlunit:htmlunit") - optional("org.seleniumhq.selenium:htmlunit-driver") - optional("org.seleniumhq.selenium:selenium-java") + optional("org.seleniumhq.selenium:htmlunit-driver") { + exclude group: "net.bytebuddy", module: "byte-buddy" + } + optional("org.seleniumhq.selenium:selenium-java") { + exclude group: "net.bytebuddy", module: "byte-buddy" + } optional("org.xmlunit:xmlunit-matchers") optional("org.skyscreamer:jsonassert") optional("com.jayway.jsonpath:json-path") @@ -41,41 +45,41 @@ dependencies { optional("io.projectreactor:reactor-test") optional("org.jetbrains.kotlinx:kotlinx-coroutines-core") optional("org.jetbrains.kotlinx:kotlinx-coroutines-reactor") - testCompile(project(":spring-context-support")) - testCompile(project(":spring-oxm")) - testCompile(testFixtures(project(":spring-beans"))) - testCompile(testFixtures(project(":spring-context"))) - testCompile(testFixtures(project(":spring-core"))) - testCompile(testFixtures(project(":spring-tx"))) - testCompile(testFixtures(project(":spring-web"))) - testCompile("javax.annotation:javax.annotation-api") - testCompile("javax.cache:cache-api") - testCompile("javax.ejb:javax.ejb-api") - testCompile("javax.interceptor:javax.interceptor-api") - testCompile("javax.mail:javax.mail-api") - testCompile("org.hibernate:hibernate-core") - testCompile("org.hibernate:hibernate-validator") - testCompile("javax.validation:validation-api") - testCompile("org.junit.platform:junit-platform-runner") { + testImplementation(project(":spring-context-support")) + testImplementation(project(":spring-oxm")) + testImplementation(testFixtures(project(":spring-beans"))) + testImplementation(testFixtures(project(":spring-context"))) + testImplementation(testFixtures(project(":spring-core"))) + testImplementation(testFixtures(project(":spring-tx"))) + testImplementation(testFixtures(project(":spring-web"))) + testImplementation("javax.annotation:javax.annotation-api") + testImplementation("javax.cache:cache-api") + testImplementation("javax.ejb:javax.ejb-api") + testImplementation("javax.interceptor:javax.interceptor-api") + testImplementation("javax.mail:javax.mail-api") + testImplementation("org.hibernate:hibernate-core") + testImplementation("org.hibernate:hibernate-validator") + testImplementation("javax.validation:validation-api") + testImplementation("org.junit.platform:junit-platform-runner") { exclude group: "junit", module: "junit" } - testCompile("org.junit.platform:junit-platform-testkit") - testCompile("com.fasterxml.jackson.core:jackson-databind") - testCompile("com.thoughtworks.xstream:xstream") - testCompile("com.rometools:rome") - testCompile("org.apache.tiles:tiles-api") - testCompile("org.apache.tiles:tiles-core") - testCompile("org.apache.tiles:tiles-servlet") - testCompile("org.hsqldb:hsqldb") - testCompile("org.apache.httpcomponents:httpclient") - testCompile("io.projectreactor.netty:reactor-netty-http") - testCompile("de.bechte.junit:junit-hierarchicalcontextrunner") - testRuntime("org.junit.vintage:junit-vintage-engine") { + testImplementation("org.junit.platform:junit-platform-testkit") + testImplementation("com.fasterxml.jackson.core:jackson-databind") + testImplementation("com.thoughtworks.xstream:xstream") + testImplementation("com.rometools:rome") + testImplementation("org.apache.tiles:tiles-api") + testImplementation("org.apache.tiles:tiles-core") + testImplementation("org.apache.tiles:tiles-servlet") + testImplementation("org.hsqldb:hsqldb") + testImplementation("org.apache.httpcomponents:httpclient") + testImplementation("io.projectreactor.netty:reactor-netty-http") + testImplementation("de.bechte.junit:junit-hierarchicalcontextrunner") + testRuntimeOnly("org.junit.vintage:junit-vintage-engine") { exclude group: "junit", module: "junit" } - testRuntime("org.glassfish:javax.el") - testRuntime("com.sun.xml.bind:jaxb-core") - testRuntime("com.sun.xml.bind:jaxb-impl") + testRuntimeOnly("org.glassfish:javax.el") + testRuntimeOnly("com.sun.xml.bind:jaxb-core") + testRuntimeOnly("com.sun.xml.bind:jaxb-impl") } task junit(type: Test) { @@ -108,7 +112,7 @@ test { task aggregateTestReports(type: TestReport) { description = "Aggregates JUnit and TestNG test reports." - destinationDir = test.reports.html.destination + destinationDir = test.reports.html.outputLocation.get().getAsFile() reportOn junit, testNG } diff --git a/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java b/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java index b7b6b9626aa8..a1b3eca3b08d 100644 --- a/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java +++ b/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java @@ -80,10 +80,16 @@ public class MockHttpServletResponse implements HttpServletResponse { private boolean writerAccessAllowed = true; - @Nullable - private String characterEncoding = WebUtils.DEFAULT_CHARACTER_ENCODING; + private String defaultCharacterEncoding = WebUtils.DEFAULT_CHARACTER_ENCODING; - private boolean charset = false; + private String characterEncoding = this.defaultCharacterEncoding; + + /** + * {@code true} if the character encoding has been explicitly set through + * {@link HttpServletResponse} methods or through a {@code charset} parameter + * on the {@code Content-Type}. + */ + private boolean characterEncodingSet = false; private final ByteArrayOutputStream content = new ByteArrayOutputStream(1024); @@ -117,6 +123,11 @@ public class MockHttpServletResponse implements HttpServletResponse { @Nullable private String errorMessage; + + //--------------------------------------------------------------------- + // Properties for MockRequestDispatcher + //--------------------------------------------------------------------- + @Nullable private String forwardedUrl; @@ -158,25 +169,54 @@ public boolean isWriterAccessAllowed() { } /** - * Return whether the character encoding has been set. - *

        If {@code false}, {@link #getCharacterEncoding()} will return a default encoding value. + * Set the default character encoding for the response. + *

        If this method is not invoked, {@code ISO-8859-1} will be used as the + * default character encoding. + *

        If the {@linkplain #getCharacterEncoding() character encoding} for the + * response has not already been explicitly set via {@link #setCharacterEncoding(String)} + * or {@link #setContentType(String)}, the character encoding for the response + * will be set to the supplied default character encoding. + * @param characterEncoding the default character encoding + * @since 5.3.10 + * @see #setCharacterEncoding(String) + * @see #setContentType(String) + */ + public void setDefaultCharacterEncoding(String characterEncoding) { + Assert.notNull(characterEncoding, "'characterEncoding' must not be null"); + this.defaultCharacterEncoding = characterEncoding; + if (!this.characterEncodingSet) { + this.characterEncoding = characterEncoding; + } + } + + /** + * Determine whether the character encoding has been explicitly set through + * {@link HttpServletResponse} methods or through a {@code charset} parameter + * on the {@code Content-Type}. + *

        If {@code false}, {@link #getCharacterEncoding()} will return the + * {@linkplain #setDefaultCharacterEncoding(String) default character encoding}. */ public boolean isCharset() { - return this.charset; + return this.characterEncodingSet; } @Override public void setCharacterEncoding(String characterEncoding) { - this.characterEncoding = characterEncoding; - this.charset = true; + setExplicitCharacterEncoding(characterEncoding); updateContentTypePropertyAndHeader(); } + private void setExplicitCharacterEncoding(String characterEncoding) { + Assert.notNull(characterEncoding, "'characterEncoding' must not be null"); + this.characterEncoding = characterEncoding; + this.characterEncodingSet = true; + } + private void updateContentTypePropertyAndHeader() { if (this.contentType != null) { String value = this.contentType; - if (this.charset && !this.contentType.toLowerCase().contains(CHARSET_PREFIX)) { - value = value + ';' + CHARSET_PREFIX + this.characterEncoding; + if (this.characterEncodingSet && !value.toLowerCase().contains(CHARSET_PREFIX)) { + value += ';' + CHARSET_PREFIX + getCharacterEncoding(); this.contentType = value; } doAddHeaderValue(HttpHeaders.CONTENT_TYPE, value, true); @@ -184,7 +224,6 @@ private void updateContentTypePropertyAndHeader() { } @Override - @Nullable public String getCharacterEncoding() { return this.characterEncoding; } @@ -199,9 +238,7 @@ public ServletOutputStream getOutputStream() { public PrintWriter getWriter() throws UnsupportedEncodingException { Assert.state(this.writerAccessAllowed, "Writer access not allowed"); if (this.writer == null) { - Writer targetWriter = (this.characterEncoding != null ? - new OutputStreamWriter(this.content, this.characterEncoding) : - new OutputStreamWriter(this.content)); + Writer targetWriter = new OutputStreamWriter(this.content, getCharacterEncoding()); this.writer = new ResponsePrintWriter(targetWriter); } return this.writer; @@ -215,14 +252,17 @@ public byte[] getContentAsByteArray() { * Get the content of the response body as a {@code String}, using the charset * specified for the response by the application, either through * {@link HttpServletResponse} methods or through a charset parameter on the - * {@code Content-Type}. + * {@code Content-Type}. If no charset has been explicitly defined, the + * {@linkplain #setDefaultCharacterEncoding(String) default character encoding} + * will be used. * @return the content as a {@code String} * @throws UnsupportedEncodingException if the character encoding is not supported * @see #getContentAsString(Charset) + * @see #setCharacterEncoding(String) + * @see #setContentType(String) */ public String getContentAsString() throws UnsupportedEncodingException { - return (this.characterEncoding != null ? - this.content.toString(this.characterEncoding) : this.content.toString()); + return this.content.toString(getCharacterEncoding()); } /** @@ -235,11 +275,12 @@ public String getContentAsString() throws UnsupportedEncodingException { * @throws UnsupportedEncodingException if the character encoding is not supported * @since 5.2 * @see #getContentAsString() + * @see #setCharacterEncoding(String) + * @see #setContentType(String) */ public String getContentAsString(Charset fallbackCharset) throws UnsupportedEncodingException { - return (isCharset() && this.characterEncoding != null ? - this.content.toString(this.characterEncoding) : - this.content.toString(fallbackCharset.name())); + String charsetName = (this.characterEncodingSet ? getCharacterEncoding() : fallbackCharset.name()); + return this.content.toString(charsetName); } @Override @@ -269,16 +310,14 @@ public void setContentType(@Nullable String contentType) { try { MediaType mediaType = MediaType.parseMediaType(contentType); if (mediaType.getCharset() != null) { - this.characterEncoding = mediaType.getCharset().name(); - this.charset = true; + setExplicitCharacterEncoding(mediaType.getCharset().name()); } } catch (Exception ex) { // Try to get charset value anyway int charsetIndex = contentType.toLowerCase().indexOf(CHARSET_PREFIX); if (charsetIndex != -1) { - this.characterEncoding = contentType.substring(charsetIndex + CHARSET_PREFIX.length()); - this.charset = true; + setExplicitCharacterEncoding(contentType.substring(charsetIndex + CHARSET_PREFIX.length())); } } updateContentTypePropertyAndHeader(); @@ -331,8 +370,8 @@ public boolean isCommitted() { @Override public void reset() { resetBuffer(); - this.characterEncoding = null; - this.charset = false; + this.characterEncoding = this.defaultCharacterEncoding; + this.characterEncodingSet = false; this.contentLength = 0; this.contentType = null; this.locale = Locale.getDefault(); @@ -343,7 +382,10 @@ public void reset() { } @Override - public void setLocale(Locale locale) { + public void setLocale(@Nullable Locale locale) { + // Although the Javadoc for javax.servlet.ServletResponse.setLocale(Locale) does not + // state how a null value for the supplied Locale should be handled, both Tomcat and + // Jetty simply ignore a null value. So we do the same here. if (locale == null) { return; } diff --git a/spring-test/src/main/java/org/springframework/test/annotation/Repeat.java b/spring-test/src/main/java/org/springframework/test/annotation/Repeat.java index e81bb9c85690..dfa062ceb2ba 100644 --- a/spring-test/src/main/java/org/springframework/test/annotation/Repeat.java +++ b/spring-test/src/main/java/org/springframework/test/annotation/Repeat.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -28,7 +28,11 @@ * *

        Note that the scope of execution to be repeated includes execution of the * test method itself as well as any set up or tear down of - * the test fixture. + * the test fixture. When used with the + * {@link org.springframework.test.context.junit4.rules.SpringMethodRule + * SpringMethodRule}, the scope additionally includes + * {@linkplain org.springframework.test.context.TestExecutionListener#prepareTestInstance + * preparation of the test instance}. * *

        This annotation may be used as a meta-annotation to create custom * composed annotations. diff --git a/spring-test/src/main/java/org/springframework/test/context/TestContextManager.java b/spring-test/src/main/java/org/springframework/test/context/TestContextManager.java index 30d67923e4fb..d93b78d88d56 100644 --- a/spring-test/src/main/java/org/springframework/test/context/TestContextManager.java +++ b/spring-test/src/main/java/org/springframework/test/context/TestContextManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -221,8 +221,12 @@ public void beforeTestClass() throws Exception { /** * Hook for preparing a test instance prior to execution of any individual - * test methods, for example for injecting dependencies, etc. Should be - * called immediately after instantiation of the test instance. + * test methods — for example, to inject dependencies. + *

        This method should be called immediately after instantiation of the test + * class or as soon after instantiation as possible (as is the case with the + * {@link org.springframework.test.context.junit4.rules.SpringMethodRule + * SpringMethodRule}). In any case, this method must be called prior to any + * framework-specific lifecycle callbacks. *

        The managed {@link TestContext} will be updated with the supplied * {@code testInstance}. *

        An attempt will be made to give each registered diff --git a/spring-test/src/main/java/org/springframework/test/context/TestExecutionListener.java b/spring-test/src/main/java/org/springframework/test/context/TestExecutionListener.java index a9b188e6e92d..e10d2422bdcc 100644 --- a/spring-test/src/main/java/org/springframework/test/context/TestExecutionListener.java +++ b/spring-test/src/main/java/org/springframework/test/context/TestExecutionListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -86,10 +86,14 @@ default void beforeTestClass(TestContext testContext) throws Exception { } /** - * Prepares the {@link Object test instance} of the supplied - * {@link TestContext test context}, for example by injecting dependencies. + * Prepares the {@linkplain Object test instance} of the supplied + * {@linkplain TestContext test context} — for example, to inject + * dependencies. *

        This method should be called immediately after instantiation of the test - * instance but prior to any framework-specific lifecycle callbacks. + * class or as soon after instantiation as possible (as is the case with the + * {@link org.springframework.test.context.junit4.rules.SpringMethodRule + * SpringMethodRule}). In any case, this method must be called prior to any + * framework-specific lifecycle callbacks. *

        The default implementation is empty. Can be overridden by * concrete classes as necessary. * @param testContext the test context for the test; never {@code null} @@ -123,8 +127,8 @@ default void beforeTestMethod(TestContext testContext) throws Exception { /** * Pre-processes a test immediately before execution of the - * {@link java.lang.reflect.Method test method} in the supplied - * {@link TestContext test context} — for example, for timing + * {@linkplain java.lang.reflect.Method test method} in the supplied + * {@linkplain TestContext test context} — for example, for timing * or logging purposes. *

        This method must be called after framework-specific * before lifecycle callbacks. @@ -143,8 +147,8 @@ default void beforeTestExecution(TestContext testContext) throws Exception { /** * Post-processes a test immediately after execution of the - * {@link java.lang.reflect.Method test method} in the supplied - * {@link TestContext test context} — for example, for timing + * {@linkplain java.lang.reflect.Method test method} in the supplied + * {@linkplain TestContext test context} — for example, for timing * or logging purposes. *

        This method must be called before framework-specific * after lifecycle callbacks. diff --git a/spring-test/src/main/java/org/springframework/test/context/junit4/rules/SpringMethodRule.java b/spring-test/src/main/java/org/springframework/test/context/junit4/rules/SpringMethodRule.java index 639ee9d6f623..57478d4bd8a6 100644 --- a/spring-test/src/main/java/org/springframework/test/context/junit4/rules/SpringMethodRule.java +++ b/spring-test/src/main/java/org/springframework/test/context/junit4/rules/SpringMethodRule.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2021 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. @@ -79,6 +79,10 @@ *

        NOTE: As of Spring Framework 4.3, this class requires JUnit 4.12 or higher. * *

        WARNING: Due to the shortcomings of JUnit rules, the + * {@code SpringMethodRule} + * {@linkplain org.springframework.test.context.TestExecutionListener#prepareTestInstance + * prepares the test instance} before {@code @Before} lifecycle methods instead of + * immediately after instantiation of the test class. In addition, the * {@code SpringMethodRule} does not support the * {@code beforeTestExecution()} and {@code afterTestExecution()} callbacks of the * {@link org.springframework.test.context.TestExecutionListener TestExecutionListener} diff --git a/spring-test/src/main/java/org/springframework/test/util/ExceptionCollector.java b/spring-test/src/main/java/org/springframework/test/util/ExceptionCollector.java new file mode 100644 index 000000000000..f53190b7aff7 --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/util/ExceptionCollector.java @@ -0,0 +1,127 @@ +/* + * Copyright 2002-2021 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 org.springframework.test.util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * {@code ExceptionCollector} is a test utility for executing code blocks, + * collecting exceptions, and generating a single {@link AssertionError} + * containing any exceptions encountered as {@linkplain Throwable#getSuppressed() + * suppressed exceptions}. + * + *

        This utility is intended to support soft assertion use cases + * similar to the {@code SoftAssertions} support in AssertJ and the + * {@code assertAll()} support in JUnit Jupiter. + * + * @author Sam Brannen + * @since 5.3.10 + */ +public class ExceptionCollector { + + private final List exceptions = new ArrayList<>(); + + + /** + * Execute the supplied {@link Executable} and track any exception thrown. + * @param executable the {@code Executable} to execute + * @see #getExceptions() + * @see #assertEmpty() + */ + public void execute(Executable executable) { + try { + executable.execute(); + } + catch (Throwable ex) { + this.exceptions.add(ex); + } + } + + /** + * Get the list of exceptions encountered in {@link #execute(Executable)}. + * @return an unmodifiable copy of the list of exceptions, potentially empty + * @see #assertEmpty() + */ + public List getExceptions() { + return Collections.unmodifiableList(this.exceptions); + } + + /** + * Assert that this {@code ExceptionCollector} does not contain any + * {@linkplain #getExceptions() exceptions}. + *

        If this collector is empty, this method is effectively a no-op. + *

        If this collector contains a single {@link Error} or {@link Exception}, + * this method rethrows the error or exception. + *

        If this collector contains a single {@link Throwable}, this method throws + * an {@link AssertionError} with the error message of the {@code Throwable} + * and with the {@code Throwable} as the {@linkplain Throwable#getCause() cause}. + *

        If this collector contains multiple exceptions, this method throws an + * {@code AssertionError} whose message is "Multiple Exceptions (#):" + * followed by a new line with the error message of each exception separated + * by a new line, with {@code #} replaced with the number of exceptions present. + * In addition, each exception will be added to the {@code AssertionError} as + * a {@link Throwable#addSuppressed(Throwable) suppressed exception}. + * @see #execute(Executable) + * @see #getExceptions() + */ + public void assertEmpty() throws Exception { + if (this.exceptions.isEmpty()) { + return; + } + + if (this.exceptions.size() == 1) { + Throwable exception = this.exceptions.get(0); + if (exception instanceof Error) { + throw (Error) exception; + } + if (exception instanceof Exception) { + throw (Exception) exception; + } + AssertionError assertionError = new AssertionError(exception.getMessage()); + assertionError.initCause(exception); + throw assertionError; + } + + StringBuilder message = new StringBuilder(); + message.append("Multiple Exceptions (").append(this.exceptions.size()).append("):"); + for (Throwable exception : this.exceptions) { + message.append('\n'); + message.append(exception.getMessage()); + } + AssertionError assertionError = new AssertionError(message); + this.exceptions.forEach(assertionError::addSuppressed); + throw assertionError; + } + + + /** + * {@code Executable} is a functional interface that can be used to implement + * any generic block of code that potentially throws a {@link Throwable}. + * + *

        The {@code Executable} interface is similar to {@link java.lang.Runnable}, + * except that an {@code Executable} can throw any kind of exception. + */ + @FunctionalInterface + public interface Executable { + + void execute() throws Throwable; + + } + +} diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/DefaultWebTestClient.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/DefaultWebTestClient.java index 8d0ec7de0c5d..8628ef262261 100644 --- a/spring-test/src/main/java/org/springframework/test/web/reactive/server/DefaultWebTestClient.java +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/DefaultWebTestClient.java @@ -44,6 +44,7 @@ import org.springframework.http.client.reactive.ClientHttpRequest; import org.springframework.lang.Nullable; import org.springframework.test.util.AssertionErrors; +import org.springframework.test.util.ExceptionCollector; import org.springframework.test.util.JsonExpectationsHelper; import org.springframework.test.util.XmlExpectationsHelper; import org.springframework.util.Assert; @@ -63,6 +64,8 @@ * Default implementation of {@link WebTestClient}. * * @author Rossen Stoyanchev + * @author Sam Brannen + * @author Michał Rowicki * @since 5.0 */ class DefaultWebTestClient implements WebTestClient { @@ -507,6 +510,30 @@ public FluxExchangeResult returnResult(ParameterizedTypeReference elem Flux body = this.response.bodyToFlux(elementTypeRef); return new FluxExchangeResult<>(this.exchangeResult, body); } + + @Override + public ResponseSpec expectAll(ResponseSpecConsumer... consumers) { + ExceptionCollector exceptionCollector = new ExceptionCollector(); + for (ResponseSpecConsumer consumer : consumers) { + exceptionCollector.execute(() -> consumer.accept(this)); + } + try { + exceptionCollector.assertEmpty(); + } + catch (RuntimeException ex) { + throw ex; + } + catch (Exception ex) { + // In theory, a ResponseSpecConsumer should never throw an Exception + // that is not a RuntimeException, but since ExceptionCollector may + // throw a checked Exception, we handle this to appease the compiler + // and in case someone uses a "sneaky throws" technique. + AssertionError assertionError = new AssertionError(ex.getMessage()); + assertionError.initCause(ex); + throw assertionError; + } + return this; + } } diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/ExchangeResult.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/ExchangeResult.java index 2359b1384738..e44c3b9f06c8 100644 --- a/spring-test/src/main/java/org/springframework/test/web/reactive/server/ExchangeResult.java +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/ExchangeResult.java @@ -56,7 +56,7 @@ */ public class ExchangeResult { - private static Log logger = LogFactory.getLog(ExchangeResult.class); + private static final Log logger = LogFactory.getLog(ExchangeResult.class); private static final List PRINTABLE_MEDIA_TYPES = Arrays.asList( MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, @@ -77,7 +77,10 @@ public class ExchangeResult { private final String uriTemplate; @Nullable - final Object mockServerResult; + private final Object mockServerResult; + + /** Ensure single logging, e.g. for expectAll. */ + private boolean diagnosticsLogged; /** @@ -121,6 +124,7 @@ public class ExchangeResult { this.timeout = other.timeout; this.uriTemplate = other.uriTemplate; this.mockServerResult = other.mockServerResult; + this.diagnosticsLogged = other.diagnosticsLogged; } @@ -218,16 +222,17 @@ public Object getMockServerResult() { } /** - * Execute the given Runnable, catch any {@link AssertionError}, decorate - * with {@code AssertionError} containing diagnostic information about the - * request and response, and then re-throw. + * Execute the given Runnable, catch any {@link AssertionError}, log details + * about the request and response at ERROR level under the class log + * category, and after that re-throw the error. */ public void assertWithDiagnostics(Runnable assertion) { try { assertion.run(); } catch (AssertionError ex) { - if (logger.isErrorEnabled()) { + if (!this.diagnosticsLogged && logger.isErrorEnabled()) { + this.diagnosticsLogged = true; logger.error("Request details for assertion failure:\n" + this); } throw ex; diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java index 6d2fcefebd70..84adf85013c5 100644 --- a/spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java @@ -86,6 +86,8 @@ * * @author Rossen Stoyanchev * @author Brian Clozel + * @author Sam Brannen + * @author Michał Rowicki * @since 5.0 * @see StatusAssertions * @see HeaderAssertions @@ -781,6 +783,34 @@ interface RequestBodyUriSpec extends RequestBodySpec, RequestHeadersUriSpecIf a single {@link Error} or {@link RuntimeException} is thrown, + * it will be rethrown. + *

        If multiple exceptions are thrown, this method will throw an + * {@link AssertionError} whose error message is a summary of all of the + * exceptions. In addition, each exception will be added as a + * {@linkplain Throwable#addSuppressed(Throwable) suppressed exception} to + * the {@code AssertionError}. + *

        This feature is similar to the {@code SoftAssertions} support in + * AssertJ and the {@code assertAll()} support in JUnit Jupiter. + * + *

        Example

        + *
        +		 * webTestClient.get().uri("/hello").exchange()
        +		 *     .expectAll(
        +		 *         responseSpec -> responseSpec.expectStatus().isOk(),
        +		 *         responseSpec -> responseSpec.expectBody(String.class).isEqualTo("Hello, World!")
        +		 *     );
        +		 * 
        + * @param consumers the list of {@code ResponseSpec} consumers + * @since 5.3.10 + */ + ResponseSpec expectAll(ResponseSpecConsumer... consumers); + /** * Assertions on the response status. */ @@ -845,6 +875,16 @@ interface ResponseSpec { * about a target type with generics. */ FluxExchangeResult returnResult(ParameterizedTypeReference elementTypeRef); + + /** + * {@link Consumer} of a {@link ResponseSpec}. + * @since 5.3.10 + * @see ResponseSpec#expectAll(ResponseSpecConsumer...) + */ + @FunctionalInterface + interface ResponseSpecConsumer extends Consumer { + } + } diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/MockMvc.java b/spring-test/src/main/java/org/springframework/test/web/servlet/MockMvc.java index a8565da45b90..0c8a28c7fd69 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/MockMvc.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/MockMvc.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -16,6 +16,7 @@ package org.springframework.test.web.servlet; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; @@ -78,6 +79,9 @@ public final class MockMvc { @Nullable private RequestBuilder defaultRequestBuilder; + @Nullable + private Charset defaultResponseCharacterEncoding; + private List defaultResultMatchers = new ArrayList<>(); private List defaultResultHandlers = new ArrayList<>(); @@ -106,6 +110,14 @@ void setDefaultRequest(@Nullable RequestBuilder requestBuilder) { this.defaultRequestBuilder = requestBuilder; } + /** + * The default character encoding to be applied to every response. + * @see org.springframework.test.web.servlet.setup.ConfigurableMockMvcBuilder#defaultResponseCharacterEncoding(Charset) + */ + void setDefaultResponseCharacterEncoding(@Nullable Charset defaultResponseCharacterEncoding) { + this.defaultResponseCharacterEncoding = defaultResponseCharacterEncoding; + } + /** * Expectations to assert after every performed request. * @see org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder#alwaysExpect(ResultMatcher) @@ -169,6 +181,10 @@ public ResultActions perform(RequestBuilder requestBuilder) throws Exception { servletResponse = mockResponse; } + if (this.defaultResponseCharacterEncoding != null) { + mockResponse.setDefaultCharacterEncoding(this.defaultResponseCharacterEncoding.name()); + } + if (requestBuilder instanceof SmartRequestBuilder) { request = ((SmartRequestBuilder) requestBuilder).postProcessRequest(request); } @@ -217,12 +233,12 @@ private MockHttpServletResponse unwrapResponseIfNecessary(ServletResponse servle } private void applyDefaultResultActions(MvcResult mvcResult) throws Exception { - for (ResultMatcher matcher : this.defaultResultMatchers) { - matcher.match(mvcResult); - } for (ResultHandler handler : this.defaultResultHandlers) { handler.handle(mvcResult); } + for (ResultMatcher matcher : this.defaultResultMatchers) { + matcher.match(mvcResult); + } } } diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/MockMvcBuilderSupport.java b/spring-test/src/main/java/org/springframework/test/web/servlet/MockMvcBuilderSupport.java index d08a96f3227d..d635b00b1bab 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/MockMvcBuilderSupport.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/MockMvcBuilderSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2021 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. @@ -16,6 +16,7 @@ package org.springframework.test.web.servlet; +import java.nio.charset.Charset; import java.util.List; import javax.servlet.Filter; @@ -37,10 +38,28 @@ * @author Rossen Stoyanchev * @author Rob Winch * @author Stephane Nicoll + * @author Sam Brannen * @since 3.2 */ public abstract class MockMvcBuilderSupport { + /** + * Delegates to {@link #createMockMvc(Filter[], MockServletConfig, WebApplicationContext, RequestBuilder, List, List, List)} + * for creation of the {@link MockMvc} instance and configures that instance + * with the supplied {@code defaultResponseCharacterEncoding}. + * @since 5.3.10 + */ + protected final MockMvc createMockMvc(Filter[] filters, MockServletConfig servletConfig, + WebApplicationContext webAppContext, @Nullable RequestBuilder defaultRequestBuilder, + @Nullable Charset defaultResponseCharacterEncoding, + List globalResultMatchers, List globalResultHandlers, + @Nullable List dispatcherServletCustomizers) { + + MockMvc mockMvc = createMockMvc(filters, servletConfig, webAppContext, defaultRequestBuilder, globalResultMatchers, globalResultHandlers, dispatcherServletCustomizers); + mockMvc.setDefaultResponseCharacterEncoding(defaultResponseCharacterEncoding); + return mockMvc; + } + protected final MockMvc createMockMvc(Filter[] filters, MockServletConfig servletConfig, WebApplicationContext webAppContext, @Nullable RequestBuilder defaultRequestBuilder, List globalResultMatchers, List globalResultHandlers, diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/ResultActions.java b/spring-test/src/main/java/org/springframework/test/web/servlet/ResultActions.java index d63a5dd4884e..f4fd6da14b58 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/ResultActions.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/ResultActions.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2021 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. @@ -16,6 +16,8 @@ package org.springframework.test.web.servlet; +import org.springframework.test.util.ExceptionCollector; + /** * Allows applying actions, such as expectations, on the result of an executed * request. @@ -25,6 +27,8 @@ * {@link org.springframework.test.web.servlet.result.MockMvcResultHandlers}. * * @author Rossen Stoyanchev + * @author Sam Brannen + * @author Michał Rowicki * @since 3.2 */ public interface ResultActions { @@ -33,8 +37,10 @@ public interface ResultActions { * Perform an expectation. * *

        Example

        + *

        You can invoke {@code andExpect()} multiple times as in the following + * example. *

        -	 * static imports: MockMvcRequestBuilders.*, MockMvcResultMatchers.*
        +	 * // static imports: MockMvcRequestBuilders.*, MockMvcResultMatchers.*
         	 *
         	 * mockMvc.perform(get("/person/1"))
         	 *   .andExpect(status().isOk())
        @@ -42,22 +48,48 @@ public interface ResultActions {
         	 *   .andExpect(jsonPath("$.person.name").value("Jason"));
         	 * 
        * - *

        Or alternatively provide all matchers as a vararg: + * @see #andExpectAll(ResultMatcher...) + */ + ResultActions andExpect(ResultMatcher matcher) throws Exception; + + /** + * Perform multiple expectations, with the guarantee that all expectations + * will be asserted even if one or more expectations fail with an exception. + *

        If a single {@link Error} or {@link Exception} is thrown, it will + * be rethrown. + *

        If multiple exceptions are thrown, this method will throw an + * {@link AssertionError} whose error message is a summary of all of the + * exceptions. In addition, each exception will be added as a + * {@linkplain Throwable#addSuppressed(Throwable) suppressed exception} to + * the {@code AssertionError}. + *

        This feature is similar to the {@code SoftAssertions} support in AssertJ + * and the {@code assertAll()} support in JUnit Jupiter. + * + *

        Example

        + *

        Instead of invoking {@code andExpect()} multiple times, you can invoke + * {@code andExpectAll()} as in the following example. *

        -	 * static imports: MockMvcRequestBuilders.*, MockMvcResultMatchers.*, ResultMatcher.matchAll
        +	 * // static imports: MockMvcRequestBuilders.*, MockMvcResultMatchers.*
         	 *
        -	 * mockMvc.perform(post("/form"))
        -	 *   .andExpect(matchAll(
        +	 * mockMvc.perform(get("/person/1"))
        +	 *   .andExpectAll(
         	 *       status().isOk(),
        -	 *       redirectedUrl("/person/1"),
        -	 *   	 model().size(1),
        -	 *       model().attributeExists("person"),
        -	 *       flash().attributeCount(1),
        -	 *       flash().attribute("message", "success!"))
        +	 *       content().contentType(MediaType.APPLICATION_JSON),
        +	 *       jsonPath("$.person.name").value("Jason")
         	 *   );
         	 * 
        + * + * @since 5.3.10 + * @see #andExpect(ResultMatcher) */ - ResultActions andExpect(ResultMatcher matcher) throws Exception; + default ResultActions andExpectAll(ResultMatcher... matchers) throws Exception { + ExceptionCollector exceptionCollector = new ExceptionCollector(); + for (ResultMatcher matcher : matchers) { + exceptionCollector.execute(() -> this.andExpect(matcher)); + } + exceptionCollector.assertEmpty(); + return this; + } /** * Perform a general action. diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/ResultMatcher.java b/spring-test/src/main/java/org/springframework/test/web/servlet/ResultMatcher.java index 1b6b409806d4..44aae68e150c 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/ResultMatcher.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/ResultMatcher.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -38,8 +38,9 @@ * MockMvc mockMvc = webAppContextSetup(wac).build(); * * mockMvc.perform(get("/form")) - * .andExpect(status().isOk()) - * .andExpect(content().mimeType(MediaType.APPLICATION_JSON)); + * .andExpectAll( + * status().isOk(), + * content().mimeType(MediaType.APPLICATION_JSON)); * * * @author Rossen Stoyanchev @@ -61,7 +62,10 @@ public interface ResultMatcher { * Static method for matching with an array of result matchers. * @param matchers the matchers * @since 5.1 + * @deprecated as of Spring Framework 5.3.10, in favor of + * {@link ResultActions#andExpectAll(ResultMatcher...)} */ + @Deprecated static ResultMatcher matchAll(ResultMatcher... matchers) { return result -> { for (ResultMatcher matcher : matchers) { diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilder.java b/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilder.java index fa52c987c667..7d76e63e7511 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilder.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilder.java @@ -377,12 +377,18 @@ private void params(MockHttpServletRequest request, UriComponents uriComponents) MockPart part; if (file != null) { part = new MockPart(pair.getName(), file.getName(), readAllBytes(file)); - part.getHeaders().setContentType(MediaType.valueOf(pair.getMimeType())); } - else { // mimic empty file upload - part = new MockPart(pair.getName(), "", null); - part.getHeaders().setContentType(MediaType.APPLICATION_OCTET_STREAM); + else { + // Support empty file upload OR file upload via setData(). + // For an empty file upload, getValue() returns an empty string, and + // getData() returns null. + // For a file upload via setData(), getData() returns the file data, and + // getValue() returns the file name (if set) or an empty string. + part = new MockPart(pair.getName(), pair.getValue(), pair.getData()); } + MediaType mediaType = (pair.getMimeType() != null ? MediaType.valueOf(pair.getMimeType()) : + MediaType.APPLICATION_OCTET_STREAM); + part.getHeaders().setContentType(mediaType); request.addPart(part); } else { diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilder.java b/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilder.java index 7a73e731f5e0..c4ec1cd91733 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilder.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -20,6 +20,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.URI; +import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.security.Principal; import java.util.ArrayList; @@ -243,6 +244,17 @@ public MockHttpServletRequestBuilder secure(boolean secure){ return this; } + /** + * Set the character encoding of the request. + * @param encoding the character encoding + * @since 5.3.10 + * @see StandardCharsets + * @see #characterEncoding(String) + */ + public MockHttpServletRequestBuilder characterEncoding(Charset encoding) { + return this.characterEncoding(encoding.name()); + } + /** * Set the character encoding of the request. * @param encoding the character encoding diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/result/ContentResultMatchers.java b/spring-test/src/main/java/org/springframework/test/web/servlet/result/ContentResultMatchers.java index 87232ae45bc6..f2d9360107f1 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/result/ContentResultMatchers.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/result/ContentResultMatchers.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -16,6 +16,7 @@ package org.springframework.test.web.servlet.result; +import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Map; @@ -43,6 +44,7 @@ * {@link MockMvcResultMatchers#content}. * * @author Rossen Stoyanchev + * @author Sam Brannen * @since 3.2 */ public class ContentResultMatchers { @@ -107,6 +109,16 @@ public ResultMatcher contentTypeCompatibleWith(MediaType contentType) { }; } + /** + * Assert the character encoding in the ServletResponse. + * @since 5.3.10 + * @see StandardCharsets + * @see #encoding(String) + */ + public ResultMatcher encoding(Charset characterEncoding) { + return encoding(characterEncoding.name()); + } + /** * Assert the character encoding in the ServletResponse. * @see HttpServletResponse#getCharacterEncoding() diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/result/PrintingResultHandler.java b/spring-test/src/main/java/org/springframework/test/web/servlet/result/PrintingResultHandler.java index a358760aa3e2..f0ea1c5b658d 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/result/PrintingResultHandler.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/result/PrintingResultHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2021 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. @@ -123,13 +123,10 @@ protected void printRequest(MockHttpServletRequest request) throws Exception { protected final HttpHeaders getRequestHeaders(MockHttpServletRequest request) { HttpHeaders headers = new HttpHeaders(); - Enumeration names = request.getHeaderNames(); + Enumeration names = request.getHeaderNames(); while (names.hasMoreElements()) { - String name = (String) names.nextElement(); - Enumeration values = request.getHeaders(name); - while (values.hasMoreElements()) { - headers.add(name, values.nextElement()); - } + String name = names.nextElement(); + headers.put(name, Collections.list(request.getHeaders(name))); } return headers; } @@ -248,14 +245,11 @@ protected void printFlashMap(FlashMap flashMap) throws Exception { * Print the response. */ protected void printResponse(MockHttpServletResponse response) throws Exception { - String body = (response.getCharacterEncoding() != null ? - response.getContentAsString() : MISSING_CHARACTER_ENCODING); - this.printer.printValue("Status", response.getStatus()); this.printer.printValue("Error message", response.getErrorMessage()); this.printer.printValue("Headers", getResponseHeaders(response)); this.printer.printValue("Content type", response.getContentType()); - this.printer.printValue("Body", body); + this.printer.printValue("Body", response.getContentAsString()); this.printer.printValue("Forwarded URL", response.getForwardedUrl()); this.printer.printValue("Redirected URL", response.getRedirectedUrl()); printCookies(response.getCookies()); diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/setup/AbstractMockMvcBuilder.java b/spring-test/src/main/java/org/springframework/test/web/servlet/setup/AbstractMockMvcBuilder.java index de05563d7043..e5ed43ce30aa 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/setup/AbstractMockMvcBuilder.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/setup/AbstractMockMvcBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2021 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. @@ -16,6 +16,7 @@ package org.springframework.test.web.servlet.setup; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; @@ -48,6 +49,7 @@ * * @author Rossen Stoyanchev * @author Stephane Nicoll + * @author Sam Brannen * @since 4.0 * @param a self reference to the builder type */ @@ -59,6 +61,9 @@ public abstract class AbstractMockMvcBuilder @Nullable private RequestBuilder defaultRequestBuilder; + @Nullable + private Charset defaultResponseCharacterEncoding; + private final List globalResultMatchers = new ArrayList<>(); private final List globalResultHandlers = new ArrayList<>(); @@ -95,6 +100,17 @@ public final T defaultRequest(RequestBuilder requestBuilder) { return self(); } + /** + * Define the default character encoding to be applied to every response. + * @param defaultResponseCharacterEncoding the default response character encoding + * @since 5.3.10 + */ + @Override + public final T defaultResponseCharacterEncoding(Charset defaultResponseCharacterEncoding) { + this.defaultResponseCharacterEncoding = defaultResponseCharacterEncoding; + return self(); + } + @Override public final T alwaysExpect(ResultMatcher resultMatcher) { this.globalResultMatchers.add(resultMatcher); @@ -157,7 +173,8 @@ public final MockMvc build() { Filter[] filterArray = this.filters.toArray(new Filter[0]); return super.createMockMvc(filterArray, mockServletConfig, wac, this.defaultRequestBuilder, - this.globalResultMatchers, this.globalResultHandlers, this.dispatcherServletCustomizers); + this.defaultResponseCharacterEncoding, this.globalResultMatchers, this.globalResultHandlers, + this.dispatcherServletCustomizers); } /** diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/setup/ConfigurableMockMvcBuilder.java b/spring-test/src/main/java/org/springframework/test/web/servlet/setup/ConfigurableMockMvcBuilder.java index a619ee7a5882..45b9f05d04a4 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/setup/ConfigurableMockMvcBuilder.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/setup/ConfigurableMockMvcBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -16,6 +16,8 @@ package org.springframework.test.web.servlet.setup; +import java.nio.charset.Charset; + import javax.servlet.Filter; import org.springframework.test.web.servlet.DispatcherServletCustomizer; @@ -28,6 +30,7 @@ * Defines common methods for building a {@code MockMvc}. * * @author Rossen Stoyanchev + * @author Sam Brannen * @since 4.1 * @param a self reference to the builder type */ @@ -81,6 +84,18 @@ public interface ConfigurableMockMvcBuilder T defaultRequest(RequestBuilder requestBuilder); + /** + * Define the default character encoding to be applied to every response. + *

        The default implementation of this method throws an + * {@link UnsupportedOperationException}. Concrete implementations are therefore + * encouraged to override this method. + * @param defaultResponseCharacterEncoding the default response character encoding + * @since 5.3.10 + */ + default T defaultResponseCharacterEncoding(Charset defaultResponseCharacterEncoding) { + throw new UnsupportedOperationException("defaultResponseCharacterEncoding is not supported by this MockMvcBuilder"); + } + /** * Define a global expectation that should always be applied to * every response. For example, status code 200 (OK), content type @@ -110,6 +125,7 @@ public interface ConfigurableMockMvcBuilder T addDispatcherServletCustomizer(DispatcherServletCustomizer customizer); diff --git a/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java b/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java index 1b45d2d36c2a..fe0f90f7b500 100644 --- a/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java +++ b/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java @@ -195,6 +195,36 @@ void setCharacterEncodingThenContentType() { assertThat(response.getCharacterEncoding()).isEqualTo("UTF-8"); } + @Test + void defaultCharacterEncoding() { + assertThat(response.isCharset()).isFalse(); + assertThat(response.getContentType()).isNull(); + assertThat(response.getCharacterEncoding()).isEqualTo("ISO-8859-1"); + + response.setDefaultCharacterEncoding("UTF-8"); + assertThat(response.isCharset()).isFalse(); + assertThat(response.getContentType()).isNull(); + assertThat(response.getCharacterEncoding()).isEqualTo("UTF-8"); + + response.setContentType("text/plain;charset=UTF-16"); + assertThat(response.isCharset()).isTrue(); + assertThat(response.getContentType()).isEqualTo("text/plain;charset=UTF-16"); + assertThat(response.getCharacterEncoding()).isEqualTo("UTF-16"); + + response.reset(); + assertThat(response.isCharset()).isFalse(); + assertThat(response.getContentType()).isNull(); + assertThat(response.getCharacterEncoding()).isEqualTo("UTF-8"); + + response.setCharacterEncoding("FOXTROT"); + assertThat(response.isCharset()).isTrue(); + assertThat(response.getContentType()).isNull(); + assertThat(response.getCharacterEncoding()).isEqualTo("FOXTROT"); + + response.setDefaultCharacterEncoding("ENIGMA"); + assertThat(response.getCharacterEncoding()).isEqualTo("FOXTROT"); + } + @Test void contentLength() { response.setContentLength(66); @@ -551,6 +581,8 @@ private void assertPrimarySessionCookie(String expectedValue) { @Test // gh-25501 void resetResetsCharset() { + assertThat(response.getContentType()).isNull(); + assertThat(response.getCharacterEncoding()).isEqualTo("ISO-8859-1"); assertThat(response.isCharset()).isFalse(); response.setCharacterEncoding("UTF-8"); assertThat(response.isCharset()).isTrue(); @@ -562,6 +594,8 @@ void resetResetsCharset() { response.reset(); + assertThat(response.getContentType()).isNull(); + assertThat(response.getCharacterEncoding()).isEqualTo("ISO-8859-1"); assertThat(response.isCharset()).isFalse(); // Do not invoke setCharacterEncoding() since that sets the charset flag to true. // response.setCharacterEncoding("UTF-8"); diff --git a/spring-test/src/test/java/org/springframework/test/context/SpringTestContextFrameworkTestSuite.java b/spring-test/src/test/java/org/springframework/test/context/SpringTestContextFrameworkTestSuite.java index d1532dfcffc1..4500d5566899 100644 --- a/spring-test/src/test/java/org/springframework/test/context/SpringTestContextFrameworkTestSuite.java +++ b/spring-test/src/test/java/org/springframework/test/context/SpringTestContextFrameworkTestSuite.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -16,12 +16,10 @@ package org.springframework.test.context; -import org.junit.platform.runner.JUnitPlatform; import org.junit.platform.suite.api.ExcludeTags; import org.junit.platform.suite.api.IncludeClassNamePatterns; import org.junit.platform.suite.api.SelectPackages; -import org.junit.platform.suite.api.UseTechnicalNames; -import org.junit.runner.RunWith; +import org.junit.platform.suite.api.Suite; /** * JUnit Platform based test suite for tests that involve the Spring TestContext @@ -42,10 +40,9 @@ * @author Sam Brannen * @since 5.2 */ -@RunWith(JUnitPlatform.class) +@Suite @SelectPackages("org.springframework.test.context") @IncludeClassNamePatterns(".*Tests?$") @ExcludeTags("failing-test-case") -@UseTechnicalNames -public class SpringTestContextFrameworkTestSuite { +class SpringTestContextFrameworkTestSuite { } diff --git a/spring-test/src/test/java/org/springframework/test/context/env/TestPropertySourceTestSuite.java b/spring-test/src/test/java/org/springframework/test/context/env/TestPropertySourceTestSuite.java index 97c5c62e2527..e67528774a8b 100644 --- a/spring-test/src/test/java/org/springframework/test/context/env/TestPropertySourceTestSuite.java +++ b/spring-test/src/test/java/org/springframework/test/context/env/TestPropertySourceTestSuite.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -16,12 +16,10 @@ package org.springframework.test.context.env; -import org.junit.platform.runner.JUnitPlatform; import org.junit.platform.suite.api.IncludeClassNamePatterns; import org.junit.platform.suite.api.IncludeEngines; import org.junit.platform.suite.api.SelectPackages; -import org.junit.platform.suite.api.UseTechnicalNames; -import org.junit.runner.RunWith; +import org.junit.platform.suite.api.Suite; import org.springframework.test.context.TestPropertySource; @@ -35,10 +33,9 @@ * @author Sam Brannen * @since 5.2 */ -@RunWith(JUnitPlatform.class) +@Suite @IncludeEngines("junit-jupiter") @SelectPackages("org.springframework.test.context.env") @IncludeClassNamePatterns(".*Tests$") -@UseTechnicalNames -public class TestPropertySourceTestSuite { +class TestPropertySourceTestSuite { } diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/SpringJUnitJupiterTestSuite.java b/spring-test/src/test/java/org/springframework/test/context/junit/SpringJUnitJupiterTestSuite.java index 0a0cf2f84ead..28c8071e1c8c 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit/SpringJUnitJupiterTestSuite.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit/SpringJUnitJupiterTestSuite.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2021 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. @@ -16,22 +16,17 @@ package org.springframework.test.context.junit; -import org.junit.platform.runner.JUnitPlatform; import org.junit.platform.suite.api.ExcludeTags; import org.junit.platform.suite.api.IncludeClassNamePatterns; import org.junit.platform.suite.api.IncludeEngines; import org.junit.platform.suite.api.SelectPackages; -import org.junit.platform.suite.api.UseTechnicalNames; -import org.junit.runner.RunWith; +import org.junit.platform.suite.api.Suite; /** - * JUnit 4 based test suite for tests that involve the Spring TestContext + * JUnit Platform based test suite for tests that involve the Spring TestContext * Framework and JUnit Jupiter (i.e., JUnit 5's programming model). * - *

        This class intentionally does not reside in the "jupiter" package - * so that the entire "jupiter" package can be excluded from the Gradle - * build. This class is therefore responsible for executing all JUnit - * Jupiter based tests in Spring's official test suite. + *

        This suite is only intended to be used manually within an IDE. * *

        Logging Configuration

        * @@ -46,11 +41,10 @@ * @author Sam Brannen * @since 5.0 */ -@RunWith(JUnitPlatform.class) +@Suite @IncludeEngines("junit-jupiter") @SelectPackages("org.springframework.test.context.junit.jupiter") @IncludeClassNamePatterns(".*Tests$") @ExcludeTags("failing-test-case") -@UseTechnicalNames public class SpringJUnitJupiterTestSuite { } diff --git a/spring-test/src/test/java/org/springframework/test/util/ExceptionCollectorTests.java b/spring-test/src/test/java/org/springframework/test/util/ExceptionCollectorTests.java new file mode 100644 index 000000000000..6bb39d407b01 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/util/ExceptionCollectorTests.java @@ -0,0 +1,151 @@ +/* + * Copyright 2002-2021 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 org.springframework.test.util; + +import org.junit.jupiter.api.Test; + +import org.springframework.test.util.ExceptionCollector.Executable; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatNoException; + +/** + * Unit tests for {@link ExceptionCollector}. + * + * @author Sam Brannen + * @since 5.3.10 + */ +public class ExceptionCollectorTests { + + private static final char EOL = '\n'; + + private final ExceptionCollector collector = new ExceptionCollector(); + + + @Test + void noExceptions() { + this.collector.execute(() -> {}); + + assertThat(this.collector.getExceptions()).isEmpty(); + assertThatNoException().isThrownBy(this.collector::assertEmpty); + } + + @Test + void oneError() { + this.collector.execute(error()); + + assertOneFailure(Error.class, "error"); + } + + @Test + void oneAssertionError() { + this.collector.execute(assertionError()); + + assertOneFailure(AssertionError.class, "assertion"); + } + + @Test + void oneCheckedException() { + this.collector.execute(checkedException()); + + assertOneFailure(Exception.class, "checked"); + } + + @Test + void oneUncheckedException() { + this.collector.execute(uncheckedException()); + + assertOneFailure(RuntimeException.class, "unchecked"); + } + + @Test + void oneThrowable() { + this.collector.execute(throwable()); + + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(this.collector::assertEmpty) + .withMessage("throwable") + .withCauseExactlyInstanceOf(Throwable.class) + .satisfies(error -> assertThat(error.getCause()).hasMessage("throwable")) + .satisfies(error -> assertThat(error).hasNoSuppressedExceptions()); + } + + private void assertOneFailure(Class expectedType, String failureMessage) { + assertThatExceptionOfType(expectedType) + .isThrownBy(this.collector::assertEmpty) + .satisfies(exception -> + assertThat(exception) + .isExactlyInstanceOf(expectedType) + .hasNoSuppressedExceptions() + .hasNoCause() + .hasMessage(failureMessage)); + } + + @Test + void multipleFailures() { + this.collector.execute(assertionError()); + this.collector.execute(checkedException()); + this.collector.execute(uncheckedException()); + this.collector.execute(error()); + this.collector.execute(throwable()); + + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(this.collector::assertEmpty) + .withMessage("Multiple Exceptions (5):" + EOL + // + "assertion" + EOL + // + "checked" + EOL + // + "unchecked" + EOL + // + "error" + EOL + // + "throwable"// + ) + .satisfies(exception -> + assertThat(exception.getSuppressed()).extracting(Object::getClass).map(Class::getSimpleName) + .containsExactly("AssertionError", "Exception", "RuntimeException", "Error", "Throwable")); + } + + private Executable throwable() { + return () -> { + throw new Throwable("throwable"); + }; + } + + private Executable error() { + return () -> { + throw new Error("error"); + }; + } + + private Executable assertionError() { + return () -> { + throw new AssertionError("assertion"); + }; + } + + private Executable checkedException() { + return () -> { + throw new Exception("checked"); + }; + } + + private Executable uncheckedException() { + return () -> { + throw new RuntimeException("unchecked"); + }; + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/web/reactive/server/samples/SoftAssertionTests.java b/spring-test/src/test/java/org/springframework/test/web/reactive/server/samples/SoftAssertionTests.java new file mode 100644 index 000000000000..db7b242fffd9 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/web/reactive/server/samples/SoftAssertionTests.java @@ -0,0 +1,74 @@ +/* + * Copyright 2002-2021 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 org.springframework.test.web.reactive.server.samples; + +import org.junit.jupiter.api.Test; + +import org.springframework.test.web.reactive.server.WebTestClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +/** + * Integration tests for {@link WebTestClient} with soft assertions. + * + * @author Michał Rowicki + * @author Sam Brannen + * @since 5.3.10 + */ +class SoftAssertionTests { + + private final WebTestClient webTestClient = WebTestClient.bindToController(new TestController()).build(); + + + @Test + void expectAll() { + this.webTestClient.get().uri("/test").exchange() + .expectAll( + responseSpec -> responseSpec.expectStatus().isOk(), + responseSpec -> responseSpec.expectBody(String.class).isEqualTo("hello") + ); + } + + @Test + void expectAllWithMultipleFailures() { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> + this.webTestClient.get().uri("/test").exchange() + .expectAll( + responseSpec -> responseSpec.expectStatus().isBadRequest(), + responseSpec -> responseSpec.expectStatus().isOk(), + responseSpec -> responseSpec.expectBody(String.class).isEqualTo("bogus") + ) + ) + .withMessage("Multiple Exceptions (2):\n" + + "Status expected:<400 BAD_REQUEST> but was:<200 OK>\n" + + "Response body expected: but was:"); + } + + + @RestController + static class TestController { + + @GetMapping("/test") + String handle() { + return "hello"; + } + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/StubMvcResult.java b/spring-test/src/test/java/org/springframework/test/web/servlet/StubMvcResult.java index 12bde4ea41aa..f5c3bba6d6a7 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/StubMvcResult.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/StubMvcResult.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 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. diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/DelegatingWebConnectionTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/DelegatingWebConnectionTests.java index 1a093caf907f..05506cfbe3b2 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/DelegatingWebConnectionTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/DelegatingWebConnectionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilderTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilderTests.java index b1f73b4741f9..96ebbb4ed529 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilderTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilderTests.java @@ -16,6 +16,7 @@ package org.springframework.test.web.servlet.htmlunit; +import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; @@ -443,6 +444,33 @@ public void buildRequestParameterMapViaWebRequestDotSetRequestParametersWithFile assertThat(part.getContentType()).isEqualTo(MimeType.TEXT_PLAIN); } + @Test // gh-27199 + public void buildRequestParameterMapViaWebRequestDotSetRequestParametersWithFileDataAsParameter() throws Exception { + String data = "{}"; + KeyDataPair keyDataPair = new KeyDataPair("key", new File("test.json"), null, MimeType.APPLICATION_JSON, StandardCharsets.UTF_8); + keyDataPair.setData(data.getBytes()); + + webRequest.setRequestParameters(Collections.singletonList(keyDataPair)); + + MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); + + assertThat(actualRequest.getParts()).hasSize(1); + Part part = actualRequest.getPart("key"); + + assertSoftly(softly -> { + softly.assertThat(part).as("part").isNotNull(); + softly.assertThat(part.getName()).as("name").isEqualTo("key"); + softly.assertThat(part.getSubmittedFileName()).as("file name").isEqualTo("test.json"); + softly.assertThat(part.getContentType()).as("content type").isEqualTo(MimeType.APPLICATION_JSON); + try { + softly.assertThat(IOUtils.toString(part.getInputStream(), StandardCharsets.UTF_8)).as("content").isEqualTo(data); + } + catch (IOException ex) { + softly.fail("failed to get InputStream", ex); + } + }); + } + @Test // gh-26799 public void buildRequestParameterMapViaWebRequestDotSetRequestParametersWithNullFileToUploadAsParameter() throws Exception { webRequest.setRequestParameters(Collections.singletonList(new KeyDataPair("key", null, null, null, (Charset) null))); @@ -453,11 +481,11 @@ public void buildRequestParameterMapViaWebRequestDotSetRequestParametersWithNull Part part = actualRequest.getPart("key"); assertSoftly(softly -> { - softly.assertThat(part).isNotNull(); + softly.assertThat(part).as("part").isNotNull(); softly.assertThat(part.getName()).as("name").isEqualTo("key"); softly.assertThat(part.getSize()).as("size").isEqualTo(0); try { - softly.assertThat(part.getInputStream()).isEmpty(); + softly.assertThat(part.getInputStream()).as("input stream").isEmpty(); } catch (IOException ex) { softly.fail("failed to get InputStream", ex); diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/UrlRegexRequestMatcherTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/UrlRegexRequestMatcherTests.java index ba7e3cda66c9..457e8fc4750d 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/UrlRegexRequestMatcherTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/UrlRegexRequestMatcherTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 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. diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilderTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilderTests.java index 47f51e1046f8..b493cbbca4d0 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilderTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -32,7 +32,6 @@ import javax.servlet.ServletContext; import javax.servlet.http.Cookie; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.http.HttpHeaders; @@ -58,28 +57,22 @@ * @author Rossen Stoyanchev * @author Sam Brannen */ -public class MockHttpServletRequestBuilderTests { +class MockHttpServletRequestBuilderTests { private final ServletContext servletContext = new MockServletContext(); - private MockHttpServletRequestBuilder builder; - - - @BeforeEach - public void setUp() { - this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/foo/bar"); - } + private MockHttpServletRequestBuilder builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/foo/bar"); @Test - public void method() { + void method() { MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertThat(request.getMethod()).isEqualTo("GET"); } @Test - public void uri() { + void uri() { String uri = "https://java.sun.com:8080/javase/6/docs/api/java/util/BitSet.html?foo=bar#and(java.util.BitSet)"; this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, uri); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); @@ -94,7 +87,7 @@ public void uri() { } @Test - public void requestUriWithEncoding() { + void requestUriWithEncoding() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/foo bar"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); @@ -102,7 +95,7 @@ public void requestUriWithEncoding() { } @Test // SPR-13435 - public void requestUriWithDoubleSlashes() throws URISyntaxException { + void requestUriWithDoubleSlashes() throws URISyntaxException { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, new URI("/test//currentlyValid/0")); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); @@ -110,13 +103,13 @@ public void requestUriWithDoubleSlashes() throws URISyntaxException { } @Test // gh-24556 - public void requestUriWithoutScheme() { + void requestUriWithoutScheme() { assertThatIllegalArgumentException().isThrownBy(() -> MockMvcRequestBuilders.get("localhost:8080/path")) .withMessage("'url' should start with a path or be a complete HTTP URL: localhost:8080/path"); } @Test - public void contextPathEmpty() { + void contextPathEmpty() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/foo"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); @@ -126,7 +119,7 @@ public void contextPathEmpty() { } @Test - public void contextPathServletPathEmpty() { + void contextPathServletPathEmpty() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/travel/hotels/42"); this.builder.contextPath("/travel"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); @@ -137,7 +130,7 @@ public void contextPathServletPathEmpty() { } @Test - public void contextPathServletPath() { + void contextPathServletPath() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/travel/main/hotels/42"); this.builder.contextPath("/travel"); this.builder.servletPath("/main"); @@ -150,7 +143,7 @@ public void contextPathServletPath() { } @Test - public void contextPathServletPathInfoEmpty() { + void contextPathServletPathInfoEmpty() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/travel/hotels/42"); this.builder.contextPath("/travel"); this.builder.servletPath("/hotels/42"); @@ -162,7 +155,7 @@ public void contextPathServletPathInfoEmpty() { } @Test - public void contextPathServletPathInfo() { + void contextPathServletPathInfo() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/"); this.builder.servletPath("/index.html"); this.builder.pathInfo(null); @@ -174,7 +167,7 @@ public void contextPathServletPathInfo() { } @Test // SPR-16453 - public void pathInfoIsDecoded() { + void pathInfoIsDecoded() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/travel/hotels 42"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); @@ -182,7 +175,7 @@ public void pathInfoIsDecoded() { } @Test - public void contextPathServletPathInvalid() { + void contextPathServletPathInvalid() { testContextPathServletPathInvalid("/Foo", "", "Request URI [/foo/bar] does not start with context path [/Foo]"); testContextPathServletPathInvalid("foo", "", "Context path must start with a '/'"); testContextPathServletPathInvalid("/foo/", "", "Context path must not end with a '/'"); @@ -204,7 +197,7 @@ private void testContextPathServletPathInvalid(String contextPath, String servle } @Test - public void requestUriAndFragment() { + void requestUriAndFragment() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/foo#bar"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); @@ -212,28 +205,28 @@ public void requestUriAndFragment() { } @Test - public void requestParameter() { + void requestParameter() { this.builder.param("foo", "bar", "baz"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); Map parameterMap = request.getParameterMap(); - assertThat(parameterMap.get("foo")).isEqualTo(new String[] {"bar", "baz"}); + assertThat(parameterMap.get("foo")).containsExactly("bar", "baz"); } @Test - public void requestParameterFromQuery() { + void requestParameterFromQuery() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/?foo=bar&foo=baz"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); Map parameterMap = request.getParameterMap(); - assertThat(parameterMap.get("foo")).isEqualTo(new String[] {"bar", "baz"}); + assertThat(parameterMap.get("foo")).containsExactly("bar", "baz"); assertThat(request.getQueryString()).isEqualTo("foo=bar&foo=baz"); } @Test - public void requestParameterFromQueryList() { + void requestParameterFromQueryList() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/?foo[0]=bar&foo[1]=baz"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); @@ -244,19 +237,19 @@ public void requestParameterFromQueryList() { } @Test - public void queryParameter() { + void queryParameter() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/"); this.builder.queryParam("foo", "bar"); this.builder.queryParam("foo", "baz"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); - assertThat(request.getParameterMap().get("foo")).isEqualTo(new String[] {"bar", "baz"}); + assertThat(request.getParameterMap().get("foo")).containsExactly("bar", "baz"); assertThat(request.getQueryString()).isEqualTo("foo=bar&foo=baz"); } @Test - public void queryParameterMap() { + void queryParameterMap() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/"); MultiValueMap queryParams = new LinkedMultiValueMap<>(); List values = new ArrayList<>(); @@ -267,12 +260,12 @@ public void queryParameterMap() { MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); - assertThat(request.getParameterMap().get("foo")).isEqualTo(new String[] {"bar", "baz"}); + assertThat(request.getParameterMap().get("foo")).containsExactly("bar", "baz"); assertThat(request.getQueryString()).isEqualTo("foo=bar&foo=baz"); } @Test - public void queryParameterList() { + void queryParameterList() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/"); this.builder.queryParam("foo[0]", "bar"); this.builder.queryParam("foo[1]", "baz"); @@ -285,7 +278,7 @@ public void queryParameterList() { } @Test - public void requestParameterFromQueryWithEncoding() { + void requestParameterFromQueryWithEncoding() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/?foo={value}", "bar=baz"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); @@ -295,18 +288,18 @@ public void requestParameterFromQueryWithEncoding() { } @Test // SPR-11043 - public void requestParameterFromQueryNull() { + void requestParameterFromQueryNull() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/?foo"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); Map parameterMap = request.getParameterMap(); - assertThat(parameterMap.get("foo")).isEqualTo(new String[] {null}); + assertThat(parameterMap.get("foo")).containsExactly((String) null); assertThat(request.getQueryString()).isEqualTo("foo"); } @Test // SPR-13801 - public void requestParameterFromMultiValueMap() throws Exception { + void requestParameterFromMultiValueMap() throws Exception { MultiValueMap params = new LinkedMultiValueMap<>(); params.add("foo", "bar"); params.add("foo", "baz"); @@ -315,11 +308,11 @@ public void requestParameterFromMultiValueMap() throws Exception { MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); - assertThat(request.getParameterMap().get("foo")).isEqualTo(new String[] {"bar", "baz"}); + assertThat(request.getParameterMap().get("foo")).containsExactly("bar", "baz"); } @Test - public void requestParameterFromRequestBodyFormData() throws Exception { + void requestParameterFromRequestBodyFormData() throws Exception { String contentType = "application/x-www-form-urlencoded;charset=UTF-8"; String body = "name+1=value+1&name+2=value+A&name+2=value+B&name+3"; @@ -327,13 +320,13 @@ public void requestParameterFromRequestBodyFormData() throws Exception { .contentType(contentType).content(body.getBytes(StandardCharsets.UTF_8)) .buildRequest(this.servletContext); - assertThat(request.getParameterMap().get("name 1")).isEqualTo(new String[] {"value 1"}); - assertThat(request.getParameterMap().get("name 2")).isEqualTo(new String[] {"value A", "value B"}); - assertThat(request.getParameterMap().get("name 3")).isEqualTo(new String[] {null}); + assertThat(request.getParameterMap().get("name 1")).containsExactly("value 1"); + assertThat(request.getParameterMap().get("name 2")).containsExactly("value A", "value B"); + assertThat(request.getParameterMap().get("name 3")).containsExactly((String) null); } @Test - public void acceptHeader() { + void acceptHeader() { this.builder.accept(MediaType.TEXT_HTML, MediaType.APPLICATION_XML); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); @@ -346,14 +339,14 @@ public void acceptHeader() { } @Test // gh-2079 - public void acceptHeaderWithInvalidValues() { + void acceptHeaderWithInvalidValues() { this.builder.accept("any", "any2"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertThat(request.getHeader("Accept")).isEqualTo("any, any2"); } @Test - public void contentType() { + void contentType() { this.builder.contentType(MediaType.TEXT_HTML); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); @@ -366,7 +359,7 @@ public void contentType() { } @Test - public void contentTypeViaString() { + void contentTypeViaString() { this.builder.contentType("text/html"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); @@ -379,14 +372,14 @@ public void contentTypeViaString() { } @Test // gh-2079 - public void contentTypeWithInvalidValue() { + void contentTypeWithInvalidValue() { this.builder.contentType("any"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertThat(request.getContentType()).isEqualTo("any"); } @Test // SPR-11308 - public void contentTypeViaHeader() { + void contentTypeViaHeader() { this.builder.header("Content-Type", MediaType.TEXT_HTML_VALUE); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); String contentType = request.getContentType(); @@ -395,14 +388,14 @@ public void contentTypeViaHeader() { } @Test // gh-2079 - public void contentTypeViaHeaderWithInvalidValue() { + void contentTypeViaHeaderWithInvalidValue() { this.builder.header("Content-Type", "yaml"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertThat(request.getContentType()).isEqualTo("yaml"); } @Test // SPR-11308 - public void contentTypeViaMultipleHeaderValues() { + void contentTypeViaMultipleHeaderValues() { this.builder.header("Content-Type", MediaType.TEXT_HTML_VALUE, MediaType.ALL_VALUE); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); @@ -410,7 +403,7 @@ public void contentTypeViaMultipleHeaderValues() { } @Test - public void body() throws IOException { + void body() throws IOException { byte[] body = "Hello World".getBytes("UTF-8"); this.builder.content(body); @@ -422,7 +415,7 @@ public void body() throws IOException { } @Test - public void header() { + void header() { this.builder.header("foo", "bar", "baz"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); @@ -434,7 +427,7 @@ public void header() { } @Test - public void headers() { + void headers() { HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.APPLICATION_JSON); httpHeaders.put("foo", Arrays.asList("bar", "baz")); @@ -450,7 +443,7 @@ public void headers() { } @Test - public void cookie() { + void cookie() { Cookie cookie1 = new Cookie("foo", "bar"); Cookie cookie2 = new Cookie("baz", "qux"); this.builder.cookie(cookie1, cookie2); @@ -466,13 +459,13 @@ public void cookie() { } @Test - public void noCookies() { + void noCookies() { MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertThat(request.getCookies()).isNull(); } @Test - public void locale() { + void locale() { Locale locale = new Locale("nl", "nl"); this.builder.locale(locale); @@ -482,17 +475,20 @@ public void locale() { } @Test - public void characterEncoding() { + void characterEncoding() { String encoding = "UTF-8"; - this.builder.characterEncoding(encoding); + this.builder.characterEncoding(encoding); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); - assertThat(request.getCharacterEncoding()).isEqualTo(encoding); + + this.builder.characterEncoding(StandardCharsets.ISO_8859_1); + request = this.builder.buildRequest(this.servletContext); + assertThat(request.getCharacterEncoding()).isEqualTo(StandardCharsets.ISO_8859_1.name()); } @Test - public void requestAttribute() { + void requestAttribute() { this.builder.requestAttr("foo", "bar"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); @@ -500,7 +496,7 @@ public void requestAttribute() { } @Test - public void sessionAttribute() { + void sessionAttribute() { this.builder.sessionAttr("foo", "bar"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); @@ -508,7 +504,7 @@ public void sessionAttribute() { } @Test - public void sessionAttributes() { + void sessionAttributes() { Map map = new HashMap<>(); map.put("foo", "bar"); this.builder.sessionAttrs(map); @@ -519,7 +515,7 @@ public void sessionAttributes() { } @Test - public void session() { + void session() { MockHttpSession session = new MockHttpSession(this.servletContext); session.setAttribute("foo", "bar"); this.builder.session(session); @@ -533,7 +529,7 @@ public void session() { } @Test - public void flashAttribute() { + void flashAttribute() { this.builder.flashAttr("foo", "bar"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); @@ -543,7 +539,7 @@ public void flashAttribute() { } @Test - public void principal() { + void principal() { User user = new User(); this.builder.principal(user); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); @@ -552,7 +548,7 @@ public void principal() { } @Test // SPR-12945 - public void mergeInvokesDefaultRequestPostProcessorFirst() { + void mergeInvokesDefaultRequestPostProcessorFirst() { final String ATTR = "ATTR"; final String EXPECTED = "override"; @@ -570,7 +566,7 @@ public void mergeInvokesDefaultRequestPostProcessorFirst() { } @Test // SPR-13719 - public void arbitraryMethod() { + void arbitraryMethod() { String httpMethod = "REPort"; URI url = UriComponentsBuilder.fromPath("/foo/{bar}").buildAndExpand(42).toUri(); this.builder = new MockHttpServletRequestBuilder(httpMethod, url); diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/result/HeaderResultMatchersTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/result/HeaderResultMatchersTests.java index 19d79f1f4c75..496e9e7834b8 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/result/HeaderResultMatchersTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/result/HeaderResultMatchersTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 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. diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/result/PrintingResultHandlerTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/result/PrintingResultHandlerTests.java index b97f8d3d1f64..f91c39fda969 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/result/PrintingResultHandlerTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/result/PrintingResultHandlerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -238,16 +238,6 @@ public void printResponseWithDefaultCharacterEncoding() throws Exception { assertValue("MockHttpServletResponse", "Body", "text"); } - @Test - public void printResponseWithoutCharacterEncoding() throws Exception { - this.response.setCharacterEncoding(null); - this.response.getWriter().print("text"); - - this.handler.handle(this.mvcResult); - - assertValue("MockHttpServletResponse", "Body", ""); - } - @Test public void printHandlerNull() throws Exception { StubMvcResult mvcResult = new StubMvcResult(this.request, null, null, null, null, null, this.response); diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/context/JavaConfigTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/context/JavaConfigTests.java index e96c0c1f6cbe..9cde95fe2ce3 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/context/JavaConfigTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/context/JavaConfigTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -47,11 +47,13 @@ import org.springframework.web.servlet.view.tiles3.TilesConfigurer; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.mockito.BDDMockito.given; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.forwardedUrl; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -61,6 +63,7 @@ * @author Rossen Stoyanchev * @author Sam Brannen * @author Sebastien Deleuze + * @author Michał Rowicki */ @ExtendWith(SpringExtension.class) @WebAppConfiguration("classpath:META-INF/web-resources") @@ -93,9 +96,38 @@ public void setup() { public void person() throws Exception { this.mockMvc.perform(get("/person/5").accept(MediaType.APPLICATION_JSON)) .andDo(print()) - .andExpect(status().isOk()) - .andExpect(request().asyncNotStarted()) - .andExpect(content().string("{\"name\":\"Joe\",\"someDouble\":0.0,\"someBoolean\":false}")); + .andExpectAll( + status().isOk(), + request().asyncNotStarted(), + content().string("{\"name\":\"Joe\",\"someDouble\":0.0,\"someBoolean\":false}"), + jsonPath("$.name").value("Joe") + ); + } + + @Test + public void andExpectAllWithOneFailure() { + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(() -> this.mockMvc.perform(get("/person/5").accept(MediaType.APPLICATION_JSON)) + .andExpectAll( + status().isBadGateway(), + request().asyncNotStarted(), + jsonPath("$.name").value("Joe"))) + .withMessage("Status expected:<502> but was:<200>") + .satisfies(error -> assertThat(error).hasNoSuppressedExceptions()); + } + + @Test + public void andExpectAllWithMultipleFailures() { + assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> + this.mockMvc.perform(get("/person/5").accept(MediaType.APPLICATION_JSON)) + .andExpectAll( + status().isBadGateway(), + request().asyncNotStarted(), + jsonPath("$.name").value("Joe"), + jsonPath("$.name").value("Jane") + )) + .withMessage("Multiple Exceptions (2):\nStatus expected:<502> but was:<200>\nJSON path \"$.name\" expected: but was:") + .satisfies(error -> assertThat(error.getSuppressed()).hasSize(2)); } @Test diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/context/PersonController.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/context/PersonController.java index 31781062ba63..0ef78f3a6d4f 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/context/PersonController.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/context/PersonController.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2020 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. diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/context/PersonDao.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/context/PersonDao.java index 4001526e94c7..e06c983d720d 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/context/PersonDao.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/context/PersonDao.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2019 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. diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/ResponseBodyTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/ResponseBodyTests.java index 2799b24d191e..26b90936dfdc 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/ResponseBodyTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/ResponseBodyTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -16,8 +16,6 @@ package org.springframework.test.web.servlet.samples.standalone; -import javax.validation.constraints.NotNull; - import org.junit.jupiter.api.Test; import org.springframework.http.MediaType; @@ -25,6 +23,8 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; @@ -42,11 +42,14 @@ class ResponseBodyTests { @Test void json() throws Exception { - standaloneSetup(new PersonController()).build() - .perform(get("/person/Lee").accept(MediaType.APPLICATION_JSON)) + standaloneSetup(new PersonController()).defaultResponseCharacterEncoding(UTF_8).build() + // We use a name containing an umlaut to test UTF-8 encoding for the request and the response. + .perform(get("/person/Jürgen").characterEncoding(UTF_8).accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(content().contentType("application/json")) - .andExpect(jsonPath("$.name").value("Lee")) + .andExpect(content().encoding(UTF_8)) + .andExpect(content().string(containsString("Jürgen"))) + .andExpect(jsonPath("$.name").value("Jürgen")) .andExpect(jsonPath("$.age").value(42)) .andExpect(jsonPath("$.age").value(42.0f)) .andExpect(jsonPath("$.age").value(equalTo(42))) @@ -70,7 +73,6 @@ Person get(@PathVariable String name) { @SuppressWarnings("unused") private static class Person { - @NotNull private final String name; private int age; diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resulthandlers/PrintingResultHandlerIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resulthandlers/PrintingResultHandlerIntegrationTests.java new file mode 100644 index 000000000000..9d47134e0fb6 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resulthandlers/PrintingResultHandlerIntegrationTests.java @@ -0,0 +1,97 @@ +/* + * Copyright 2002-2021 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 org.springframework.test.web.servlet.samples.standalone.resulthandlers; + +import java.io.StringWriter; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; + +import org.junit.jupiter.api.Test; + +import org.springframework.test.web.servlet.result.PrintingResultHandler; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; + +/** + * Integration tests for {@link PrintingResultHandler}. + * + * @author Sam Brannen + * @author Rossen Stoyanchev + * @since 5.3.10 + * @see PrintingResultHandlerSmokeTests + * @see org.springframework.test.web.servlet.result.PrintingResultHandlerTests + */ +class PrintingResultHandlerIntegrationTests { + + @Test + void printMvcResultsToWriter() throws Exception { + StringWriter writer = new StringWriter(); + + standaloneSetup(new SimpleController()) + .alwaysDo(print(writer)) + .build() + .perform(get("/").content("Hello Request".getBytes()).characterEncoding("ISO-8859-1")) + .andExpect(content().string("Hello Response")); + + assertThat(writer).asString() + .contains("Hello Request") + .contains("Hello Response") + .contains("Headers = [Set-Cookie:\"enigma=42\", Content-Type:\"text/plain;charset=ISO-8859-1\", Content-Length:\"14\"]"); + } + + @Test + void printMvcResultsToWriterWithFailingGlobalResultMatcher() throws Exception { + StringWriter writer = new StringWriter(); + + try { + standaloneSetup(new SimpleController()) + .alwaysDo(print(writer)) + .alwaysExpect(content().string("Boom!")) + .build() + .perform(get("/").content("Hello Request".getBytes()).characterEncoding("ISO-8859-1")); + fail("AssertionError is expected to be thrown."); + } + catch (AssertionError error) { + assertThat(error).hasMessageContaining("Boom!"); + } + + assertThat(writer).asString() + .contains("Hello Request") + .contains("Hello Response") + .contains("Headers = [Set-Cookie:\"enigma=42\", Content-Type:\"text/plain;charset=ISO-8859-1\", Content-Length:\"14\"]"); + } + + + @RestController + private static class SimpleController { + + @GetMapping("/") + String hello(HttpServletResponse response) { + response.addCookie(new Cookie("enigma", "42")); + return "Hello Response"; + } + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resulthandlers/PrintingResultHandlerSmokeTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resulthandlers/PrintingResultHandlerSmokeTests.java index 7d23bebc0b56..1600c095263a 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resulthandlers/PrintingResultHandlerSmokeTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resulthandlers/PrintingResultHandlerSmokeTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/ContentAssertionTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/ContentAssertionTests.java index 65d0ede06ca9..2efc51e4afb5 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/ContentAssertionTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/ContentAssertionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -16,14 +16,14 @@ package org.springframework.test.web.servlet.samples.standalone.resultmatchers; -import org.junit.jupiter.api.BeforeEach; +import java.nio.charset.StandardCharsets; + import org.junit.jupiter.api.Test; import org.springframework.http.MediaType; -import org.springframework.stereotype.Controller; import org.springframework.test.web.servlet.MockMvc; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; @@ -37,6 +37,7 @@ * the character encoding. * * @author Rossen Stoyanchev + * @author Sam Brannen * * @see JsonPathAssertionTests * @see XmlContentAssertionTests @@ -44,15 +45,11 @@ */ public class ContentAssertionTests { - private MockMvc mockMvc; + private final MockMvc mockMvc = standaloneSetup(new SimpleController()).alwaysExpect(status().isOk()).build(); - @BeforeEach - public void setup() { - this.mockMvc = standaloneSetup(new SimpleController()).alwaysExpect(status().isOk()).build(); - } @Test - public void testContentType() throws Exception { + void contentType() throws Exception { this.mockMvc.perform(get("/handle").accept(MediaType.TEXT_PLAIN)) .andExpect(content().contentType(MediaType.valueOf("text/plain;charset=ISO-8859-1"))) .andExpect(content().contentType("text/plain;charset=ISO-8859-1")) @@ -67,8 +64,7 @@ public void testContentType() throws Exception { } @Test - public void testContentAsString() throws Exception { - + void contentAsString() throws Exception { this.mockMvc.perform(get("/handle").accept(MediaType.TEXT_PLAIN)) .andExpect(content().string("Hello world!")); @@ -81,8 +77,7 @@ public void testContentAsString() throws Exception { } @Test - public void testContentAsBytes() throws Exception { - + void contentAsBytes() throws Exception { this.mockMvc.perform(get("/handle").accept(MediaType.TEXT_PLAIN)) .andExpect(content().bytes("Hello world!".getBytes("ISO-8859-1"))); @@ -91,36 +86,41 @@ public void testContentAsBytes() throws Exception { } @Test - public void testContentStringMatcher() throws Exception { + void contentStringMatcher() throws Exception { this.mockMvc.perform(get("/handle").accept(MediaType.TEXT_PLAIN)) .andExpect(content().string(containsString("world"))); } @Test - public void testCharacterEncoding() throws Exception { - + void characterEncoding() throws Exception { this.mockMvc.perform(get("/handle").accept(MediaType.TEXT_PLAIN)) .andExpect(content().encoding("ISO-8859-1")) .andExpect(content().string(containsString("world"))); + this.mockMvc.perform(get("/handle").accept(MediaType.TEXT_PLAIN)) + .andExpect(content().encoding(StandardCharsets.ISO_8859_1)) + .andExpect(content().string(containsString("world"))); + this.mockMvc.perform(get("/handleUtf8")) .andExpect(content().encoding("UTF-8")) .andExpect(content().bytes("\u3053\u3093\u306b\u3061\u306f\u4e16\u754c\uff01".getBytes("UTF-8"))); + + this.mockMvc.perform(get("/handleUtf8")) + .andExpect(content().encoding(StandardCharsets.UTF_8)) + .andExpect(content().bytes("\u3053\u3093\u306b\u3061\u306f\u4e16\u754c\uff01".getBytes("UTF-8"))); } - @Controller + @RestController private static class SimpleController { - @RequestMapping(value="/handle", produces="text/plain") - @ResponseBody - public String handle() { + @GetMapping(path="/handle", produces="text/plain") + String handle() { return "Hello world!"; } - @RequestMapping(value="/handleUtf8", produces="text/plain;charset=UTF-8") - @ResponseBody - public String handleWithCharset() { + @GetMapping(path="/handleUtf8", produces="text/plain;charset=UTF-8") + String handleWithCharset() { return "\u3053\u3093\u306b\u3061\u306f\u4e16\u754c\uff01"; // "Hello world! (Japanese) } } diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/FlashAttributeAssertionTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/FlashAttributeAssertionTests.java index a6a5b7fc086b..0ffc879e9029 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/FlashAttributeAssertionTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/FlashAttributeAssertionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/ModelAssertionTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/ModelAssertionTests.java index 11473a31ab1f..a22b760bc82f 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/ModelAssertionTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/ModelAssertionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/RequestAttributeAssertionTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/RequestAttributeAssertionTests.java index 7f98ce330070..c28a9190c67b 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/RequestAttributeAssertionTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/RequestAttributeAssertionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/SessionAttributeAssertionTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/SessionAttributeAssertionTests.java index d60a4c1428b8..9479894033a4 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/SessionAttributeAssertionTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/SessionAttributeAssertionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. diff --git a/spring-tx/spring-tx.gradle b/spring-tx/spring-tx.gradle index 99c829892646..f3ec8c3f3ac3 100644 --- a/spring-tx/spring-tx.gradle +++ b/spring-tx/spring-tx.gradle @@ -3,11 +3,10 @@ description = "Spring Transaction" apply plugin: "kotlin" dependencies { - compile(project(":spring-beans")) - compile(project(":spring-core")) + api(project(":spring-beans")) + api(project(":spring-core")) optional(project(":spring-aop")) optional(project(":spring-context")) // for JCA, @EnableTransactionManagement - optional(project(":kotlin-coroutines")) optional("javax.ejb:javax.ejb-api") optional("javax.interceptor:javax.interceptor-api") optional("javax.resource:javax.resource-api") @@ -19,11 +18,11 @@ dependencies { optional("org.jetbrains.kotlin:kotlin-stdlib") optional("org.jetbrains.kotlinx:kotlinx-coroutines-core") optional("org.jetbrains.kotlinx:kotlinx-coroutines-reactor") - testCompile(testFixtures(project(":spring-beans"))) - testCompile(testFixtures(project(":spring-context"))) - testCompile(testFixtures(project(":spring-core"))) - testCompile("org.aspectj:aspectjweaver") - testCompile("org.codehaus.groovy:groovy") - testCompile("org.eclipse.persistence:javax.persistence") - testCompile("io.projectreactor:reactor-test") + testImplementation(testFixtures(project(":spring-beans"))) + testImplementation(testFixtures(project(":spring-context"))) + testImplementation(testFixtures(project(":spring-core"))) + testImplementation("org.aspectj:aspectjweaver") + testImplementation("org.codehaus.groovy:groovy") + testImplementation("org.eclipse.persistence:javax.persistence") + testImplementation("io.projectreactor:reactor-test") } diff --git a/spring-tx/src/main/java/org/springframework/transaction/support/TransactionSynchronizationManager.java b/spring-tx/src/main/java/org/springframework/transaction/support/TransactionSynchronizationManager.java index 3b6e1558acfc..55b3b8c788c6 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/support/TransactionSynchronizationManager.java +++ b/spring-tx/src/main/java/org/springframework/transaction/support/TransactionSynchronizationManager.java @@ -24,9 +24,6 @@ import java.util.Map; import java.util.Set; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - import org.springframework.core.NamedThreadLocal; import org.springframework.core.OrderComparator; import org.springframework.lang.Nullable; @@ -76,8 +73,6 @@ */ public abstract class TransactionSynchronizationManager { - private static final Log logger = LogFactory.getLog(TransactionSynchronizationManager.class); - private static final ThreadLocal> resources = new NamedThreadLocal<>("Transactional resources"); diff --git a/spring-web/spring-web.gradle b/spring-web/spring-web.gradle index 6d1ca73a86b2..716ecb4cecf3 100644 --- a/spring-web/spring-web.gradle +++ b/spring-web/spring-web.gradle @@ -4,9 +4,8 @@ apply plugin: "kotlin" apply plugin: "kotlinx-serialization" dependencies { - compile(project(":spring-beans")) - compile(project(":spring-core")) - compileOnly(project(":kotlin-coroutines")) + api(project(":spring-beans")) + api(project(":spring-core")) compileOnly("io.projectreactor.tools:blockhound") optional(project(":spring-aop")) optional(project(":spring-context")) @@ -58,30 +57,30 @@ dependencies { optional("org.jetbrains.kotlin:kotlin-reflect") optional("org.jetbrains.kotlin:kotlin-stdlib") optional("org.jetbrains.kotlinx:kotlinx-serialization-json") - testCompile(testFixtures(project(":spring-beans"))) - testCompile(testFixtures(project(":spring-context"))) - testCompile(testFixtures(project(":spring-core"))) - testCompile("io.projectreactor:reactor-test") - testCompile("org.apache.taglibs:taglibs-standard-jstlel") - testCompile("com.fasterxml.jackson.datatype:jackson-datatype-jdk8") - testCompile("com.fasterxml.jackson.datatype:jackson-datatype-joda") - testCompile("com.fasterxml.jackson.datatype:jackson-datatype-jsr310") - testCompile("com.fasterxml.jackson.module:jackson-module-kotlin") - testCompile("org.apache.tomcat:tomcat-util") - testCompile("org.apache.tomcat.embed:tomcat-embed-core") - testCompile("org.eclipse.jetty:jetty-server") - testCompile("org.eclipse.jetty:jetty-servlet") - testCompile("com.squareup.okhttp3:mockwebserver") - testCompile("org.jetbrains.kotlin:kotlin-reflect") - testCompile("org.skyscreamer:jsonassert") - testCompile("org.xmlunit:xmlunit-assertj") - testCompile("org.xmlunit:xmlunit-matchers") - testCompile("io.projectreactor.tools:blockhound") - testRuntime("com.sun.mail:javax.mail") - testRuntime("com.sun.xml.bind:jaxb-core") - testRuntime("com.sun.xml.bind:jaxb-impl") - testRuntime("javax.json:javax.json-api") - testRuntime("org.apache.johnzon:johnzon-jsonb") + testImplementation(testFixtures(project(":spring-beans"))) + testImplementation(testFixtures(project(":spring-context"))) + testImplementation(testFixtures(project(":spring-core"))) + testImplementation("io.projectreactor:reactor-test") + testImplementation("org.apache.taglibs:taglibs-standard-jstlel") + testImplementation("com.fasterxml.jackson.datatype:jackson-datatype-jdk8") + testImplementation("com.fasterxml.jackson.datatype:jackson-datatype-joda") + testImplementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310") + testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin") + testImplementation("org.apache.tomcat:tomcat-util") + testImplementation("org.apache.tomcat.embed:tomcat-embed-core") + testImplementation("org.eclipse.jetty:jetty-server") + testImplementation("org.eclipse.jetty:jetty-servlet") + testImplementation("com.squareup.okhttp3:mockwebserver") + testImplementation("org.jetbrains.kotlin:kotlin-reflect") + testImplementation("org.skyscreamer:jsonassert") + testImplementation("org.xmlunit:xmlunit-assertj") + testImplementation("org.xmlunit:xmlunit-matchers") + testImplementation("io.projectreactor.tools:blockhound") + testRuntimeOnly("com.sun.mail:javax.mail") + testRuntimeOnly("com.sun.xml.bind:jaxb-core") + testRuntimeOnly("com.sun.xml.bind:jaxb-impl") + testRuntimeOnly("javax.json:javax.json-api") + testRuntimeOnly("org.apache.johnzon:johnzon-jsonb") testFixturesApi("javax.servlet:javax.servlet-api") testFixturesApi("org.junit.jupiter:junit-jupiter-api") testFixturesApi("org.junit.jupiter:junit-jupiter-params") diff --git a/spring-web/src/main/java/org/springframework/http/codec/multipart/DefaultPartHttpMessageReader.java b/spring-web/src/main/java/org/springframework/http/codec/multipart/DefaultPartHttpMessageReader.java index fcd2e3e7906c..d4248c8442d3 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/multipart/DefaultPartHttpMessageReader.java +++ b/spring-web/src/main/java/org/springframework/http/codec/multipart/DefaultPartHttpMessageReader.java @@ -191,7 +191,7 @@ public void setStreaming(boolean streaming) { * Defaults to UTF-8 as per RFC 7578. * @param headersCharset the charset to use for decoding headers * @since 5.3.6 - * @see RFC-7578 Section 5.2 + * @see RFC-7578 Section 5.1 */ public void setHeadersCharset(Charset headersCharset) { Assert.notNull(headersCharset, "HeadersCharset must not be null"); diff --git a/spring-web/src/main/java/org/springframework/http/codec/multipart/SynchronossPartHttpMessageReader.java b/spring-web/src/main/java/org/springframework/http/codec/multipart/SynchronossPartHttpMessageReader.java index e4eedfd99eca..032b787d887b 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/multipart/SynchronossPartHttpMessageReader.java +++ b/spring-web/src/main/java/org/springframework/http/codec/multipart/SynchronossPartHttpMessageReader.java @@ -356,7 +356,7 @@ public StreamStorage newStreamStorageForPartBody(Map> heade this.isFilePart = (MultipartUtils.getFileName(headers) != null); this.partSize = 0; if (maxParts > 0 && index > maxParts) { - throw new DecodingException("Too many parts (" + index + " allowed)"); + throw new DecodingException("Too many parts: Part[" + index + "] but maxParts=" + maxParts); } return this.storageFactory.newStreamStorageForPartBody(headers, index); } diff --git a/spring-web/src/main/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilder.java b/spring-web/src/main/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilder.java index 39cf383cb3a3..415113ff0596 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilder.java +++ b/spring-web/src/main/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -55,13 +55,11 @@ import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule; import com.fasterxml.jackson.dataformat.xml.XmlFactory; import com.fasterxml.jackson.dataformat.xml.XmlMapper; -import org.apache.commons.logging.Log; import org.springframework.beans.BeanUtils; import org.springframework.beans.FatalBeanException; import org.springframework.context.ApplicationContext; import org.springframework.core.KotlinDetector; -import org.springframework.http.HttpLogging; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -105,8 +103,6 @@ */ public class Jackson2ObjectMapperBuilder { - private final Log logger = HttpLogging.forLogName(getClass()); - private final Map, Class> mixIns = new LinkedHashMap<>(); private final Map, JsonSerializer> serializers = new LinkedHashMap<>(); @@ -796,6 +792,7 @@ private void addDeserializers(SimpleModule module) { module.addDeserializer((Class) type, (JsonDeserializer) deserializer)); } + @SuppressWarnings("deprecation") // on Jackson 2.13: configure(MapperFeature, boolean) private void configureFeature(ObjectMapper objectMapper, Object feature, boolean enabled) { if (feature instanceof JsonParser.Feature) { objectMapper.configure((JsonParser.Feature) feature, enabled); diff --git a/spring-web/src/main/java/org/springframework/http/server/DefaultPathContainer.java b/spring-web/src/main/java/org/springframework/http/server/DefaultPathContainer.java index 7d4571dfb88c..e3cadabe9786 100644 --- a/spring-web/src/main/java/org/springframework/http/server/DefaultPathContainer.java +++ b/spring-web/src/main/java/org/springframework/http/server/DefaultPathContainer.java @@ -165,10 +165,10 @@ private static void parsePathParamValues(String input, Charset charset, MultiVal int index = input.indexOf('='); if (index != -1) { String name = input.substring(0, index); - String value = input.substring(index + 1); - for (String v : StringUtils.commaDelimitedListToStringArray(value)) { - name = StringUtils.uriDecode(name, charset); - if (StringUtils.hasText(name)) { + name = StringUtils.uriDecode(name, charset); + if (StringUtils.hasText(name)) { + String value = input.substring(index + 1); + for (String v : StringUtils.commaDelimitedListToStringArray(value)) { output.add(name, StringUtils.uriDecode(v, charset)); } } diff --git a/spring-web/src/main/java/org/springframework/web/client/HttpMessageConverterExtractor.java b/spring-web/src/main/java/org/springframework/web/client/HttpMessageConverterExtractor.java index 771a444bd731..45cc426a0679 100644 --- a/spring-web/src/main/java/org/springframework/web/client/HttpMessageConverterExtractor.java +++ b/spring-web/src/main/java/org/springframework/web/client/HttpMessageConverterExtractor.java @@ -122,8 +122,8 @@ public T extractData(ClientHttpResponse response) throws IOException { } throw new UnknownContentTypeException(this.responseType, contentType, - response.getRawStatusCode(), response.getStatusText(), response.getHeaders(), - getResponseBody(response)); + responseWrapper.getRawStatusCode(), responseWrapper.getStatusText(), + responseWrapper.getHeaders(), getResponseBody(responseWrapper)); } /** diff --git a/spring-web/src/main/java/org/springframework/web/client/MessageBodyClientHttpResponseWrapper.java b/spring-web/src/main/java/org/springframework/web/client/MessageBodyClientHttpResponseWrapper.java index 85e1c8f1b7e8..6565adc45f93 100644 --- a/spring-web/src/main/java/org/springframework/web/client/MessageBodyClientHttpResponseWrapper.java +++ b/spring-web/src/main/java/org/springframework/web/client/MessageBodyClientHttpResponseWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -42,7 +42,7 @@ class MessageBodyClientHttpResponseWrapper implements ClientHttpResponse { private PushbackInputStream pushbackInputStream; - public MessageBodyClientHttpResponseWrapper(ClientHttpResponse response) throws IOException { + public MessageBodyClientHttpResponseWrapper(ClientHttpResponse response) { this.response = response; } diff --git a/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java b/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java index bbcef56c8bab..80d6e7999eb4 100644 --- a/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java +++ b/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java @@ -42,6 +42,7 @@ import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; +import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.ResponseStatus; @@ -102,14 +103,24 @@ public class HandlerMethod { * Create an instance from a bean instance and a method. */ public HandlerMethod(Object bean, Method method) { + this(bean, method, null); + } + + /** + * Variant of {@link #HandlerMethod(Object, Method)} that + * also accepts a {@link MessageSource} for use from sub-classes. + * @since 5.3.10 + */ + protected HandlerMethod(Object bean, Method method, @Nullable MessageSource messageSource) { Assert.notNull(bean, "Bean is required"); Assert.notNull(method, "Method is required"); this.bean = bean; this.beanFactory = null; - this.messageSource = null; + this.messageSource = messageSource; this.beanType = ClassUtils.getUserClass(bean); this.method = method; this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); + ReflectionUtils.makeAccessible(this.bridgedMethod); this.parameters = initMethodParameters(); evaluateResponseStatus(); this.description = initDescription(this.beanType, this.method); @@ -128,6 +139,7 @@ public HandlerMethod(Object bean, String methodName, Class... parameterTypes) this.beanType = ClassUtils.getUserClass(bean); this.method = bean.getClass().getMethod(methodName, parameterTypes); this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(this.method); + ReflectionUtils.makeAccessible(this.bridgedMethod); this.parameters = initMethodParameters(); evaluateResponseStatus(); this.description = initDescription(this.beanType, this.method); @@ -163,6 +175,7 @@ public HandlerMethod( this.beanType = ClassUtils.getUserClass(beanType); this.method = method; this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); + ReflectionUtils.makeAccessible(this.bridgedMethod); this.parameters = initMethodParameters(); evaluateResponseStatus(); this.description = initDescription(this.beanType, this.method); diff --git a/spring-web/src/main/java/org/springframework/web/method/support/CompositeUriComponentsContributor.java b/spring-web/src/main/java/org/springframework/web/method/support/CompositeUriComponentsContributor.java index 18a3726920c4..9c20b6f3bbd4 100644 --- a/spring-web/src/main/java/org/springframework/web/method/support/CompositeUriComponentsContributor.java +++ b/spring-web/src/main/java/org/springframework/web/method/support/CompositeUriComponentsContributor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -31,8 +31,8 @@ /** * A {@link UriComponentsContributor} containing a list of other contributors - * to delegate and also encapsulating a specific {@link ConversionService} to - * use for formatting method argument values to Strings. + * to delegate to and also encapsulating a specific {@link ConversionService} to + * use for formatting method argument values as Strings. * * @author Rossen Stoyanchev * @author Juergen Hoeller @@ -52,7 +52,7 @@ public class CompositeUriComponentsContributor implements UriComponentsContribut * {@code HandlerMethodArgumentResolvers} in {@code RequestMappingHandlerAdapter} * and provide that to this constructor. * @param contributors a collection of {@link UriComponentsContributor} - * or {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolvers}. + * or {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolvers} */ public CompositeUriComponentsContributor(UriComponentsContributor... contributors) { this.contributors = Arrays.asList((Object[]) contributors); @@ -66,7 +66,7 @@ public CompositeUriComponentsContributor(UriComponentsContributor... contributor * {@code HandlerMethodArgumentResolvers} in {@code RequestMappingHandlerAdapter} * and provide that to this constructor. * @param contributors a collection of {@link UriComponentsContributor} - * or {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolvers}. + * or {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolvers} */ public CompositeUriComponentsContributor(Collection contributors) { this(contributors, null); @@ -82,7 +82,7 @@ public CompositeUriComponentsContributor(Collection contributors) { * {@link org.springframework.format.support.DefaultFormattingConversionService} * will be used by default. * @param contributors a collection of {@link UriComponentsContributor} - * or {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolvers}. + * or {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolvers} * @param cs a ConversionService to use when method argument values * need to be formatted as Strings before being added to the URI */ @@ -91,9 +91,14 @@ public CompositeUriComponentsContributor(@Nullable Collection contributors, @ this.conversionService = (cs != null ? cs : new DefaultFormattingConversionService()); } - + /** + * Determine if this {@code CompositeUriComponentsContributor} has any + * contributors. + * @return {@code true} if this {@code CompositeUriComponentsContributor} + * was created with contributors to delegate to + */ public boolean hasContributors() { - return this.contributors.isEmpty(); + return !this.contributors.isEmpty(); } @Override @@ -139,7 +144,7 @@ else if (contributor instanceof HandlerMethodArgumentResolver) { public void contributeMethodArgument(MethodParameter parameter, Object value, UriComponentsBuilder builder, Map uriVariables) { - this.contributeMethodArgument(parameter, value, builder, uriVariables, this.conversionService); + contributeMethodArgument(parameter, value, builder, uriVariables, this.conversionService); } } diff --git a/spring-web/src/main/java/org/springframework/web/method/support/InvocableHandlerMethod.java b/spring-web/src/main/java/org/springframework/web/method/support/InvocableHandlerMethod.java index b9c9a69c9553..970afd65503d 100644 --- a/spring-web/src/main/java/org/springframework/web/method/support/InvocableHandlerMethod.java +++ b/spring-web/src/main/java/org/springframework/web/method/support/InvocableHandlerMethod.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -20,6 +20,7 @@ import java.lang.reflect.Method; import java.util.Arrays; +import org.springframework.context.MessageSource; import org.springframework.core.CoroutinesUtils; import org.springframework.core.DefaultParameterNameDiscoverer; import org.springframework.core.KotlinDetector; @@ -27,7 +28,6 @@ import org.springframework.core.ParameterNameDiscoverer; import org.springframework.lang.Nullable; import org.springframework.util.ObjectUtils; -import org.springframework.util.ReflectionUtils; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.support.SessionStatus; import org.springframework.web.bind.support.WebDataBinderFactory; @@ -71,6 +71,15 @@ public InvocableHandlerMethod(Object bean, Method method) { super(bean, method); } + /** + * Variant of {@link #InvocableHandlerMethod(Object, Method)} that + * also accepts a {@link MessageSource}, for use in sub-classes. + * @since 5.3.10 + */ + protected InvocableHandlerMethod(Object bean, Method method, @Nullable MessageSource messageSource) { + super(bean, method, messageSource); + } + /** * Construct a new handler method with the given bean instance, method name and parameters. * @param bean the object bean @@ -189,7 +198,6 @@ protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable M @Nullable protected Object doInvoke(Object... args) throws Exception { Method method = getBridgedMethod(); - ReflectionUtils.makeAccessible(method); try { if (KotlinDetector.isSuspendingFunction(method)) { return CoroutinesUtils.invokeSuspendingFunction(method, getBean(), args); diff --git a/spring-web/src/main/java/org/springframework/web/server/ResponseStatusException.java b/spring-web/src/main/java/org/springframework/web/server/ResponseStatusException.java index 8582e8625cd3..73f41c48c71b 100644 --- a/spring-web/src/main/java/org/springframework/web/server/ResponseStatusException.java +++ b/spring-web/src/main/java/org/springframework/web/server/ResponseStatusException.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -47,7 +47,7 @@ public class ResponseStatusException extends NestedRuntimeException { * @param status the HTTP status (required) */ public ResponseStatusException(HttpStatus status) { - this(status, null, null); + this(status, null); } /** @@ -57,7 +57,10 @@ public ResponseStatusException(HttpStatus status) { * @param reason the associated reason (optional) */ public ResponseStatusException(HttpStatus status, @Nullable String reason) { - this(status, reason, null); + super(""); + Assert.notNull(status, "HttpStatus is required"); + this.status = status.value(); + this.reason = reason; } /** diff --git a/spring-web/src/main/java/org/springframework/web/server/adapter/WebHttpHandlerBuilder.java b/spring-web/src/main/java/org/springframework/web/server/adapter/WebHttpHandlerBuilder.java index a73e682a9f73..7222138f44c4 100644 --- a/spring-web/src/main/java/org/springframework/web/server/adapter/WebHttpHandlerBuilder.java +++ b/spring-web/src/main/java/org/springframework/web/server/adapter/WebHttpHandlerBuilder.java @@ -433,6 +433,7 @@ public void applyTo(BlockHound.Builder builder) { // Avoid hard references potentially anywhere in spring-web (no need for structural dependency) + builder.allowBlockingCallsInside("org.springframework.http.MediaTypeFactory", ""); builder.allowBlockingCallsInside("org.springframework.web.util.HtmlUtils", ""); } } diff --git a/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java b/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java index 6787571c4c97..d378a36840a0 100644 --- a/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java +++ b/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java @@ -881,7 +881,8 @@ else if (isForwardedSslOn(headers)) { "with the removeOnly=true. Request headers: " + headers); } - if (this.scheme != null && ((this.scheme.equals("http") && "80".equals(this.port)) || + if (this.scheme != null && + (((this.scheme.equals("http") || this.scheme.equals("ws")) && "80".equals(this.port)) || ((this.scheme.equals("https") || this.scheme.equals("wss")) && "443".equals(this.port)))) { port(null); } diff --git a/spring-web/src/main/java/org/springframework/web/util/UrlPathHelper.java b/spring-web/src/main/java/org/springframework/web/util/UrlPathHelper.java index c216c25ae6f4..663dbb7566c4 100644 --- a/spring-web/src/main/java/org/springframework/web/util/UrlPathHelper.java +++ b/spring-web/src/main/java/org/springframework/web/util/UrlPathHelper.java @@ -147,7 +147,6 @@ public void setRemoveSemicolonContent(boolean removeSemicolonContent) { * Whether configured to remove ";" (semicolon) content from the request URI. */ public boolean shouldRemoveSemicolonContent() { - checkReadOnly(); return this.removeSemicolonContent; } @@ -190,7 +189,7 @@ private void checkReadOnly() { /** * {@link #getLookupPathForRequest Resolve} the lookupPath and cache it in a - * a request attribute with the key {@link #PATH_ATTRIBUTE} for subsequent + * request attribute with the key {@link #PATH_ATTRIBUTE} for subsequent * access via {@link #getResolvedLookupPath(ServletRequest)}. * @param request the current request * @return the resolved path diff --git a/spring-web/src/test/java/org/springframework/http/client/reactive/ClientHttpConnectorTests.java b/spring-web/src/test/java/org/springframework/http/client/reactive/ClientHttpConnectorTests.java index 3c3debef9790..0f30c2391e05 100644 --- a/spring-web/src/test/java/org/springframework/http/client/reactive/ClientHttpConnectorTests.java +++ b/spring-web/src/test/java/org/springframework/http/client/reactive/ClientHttpConnectorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -77,7 +77,9 @@ void stopServer() throws IOException { server.shutdown(); } - @ParameterizedTest + // Do not auto-close arguments since HttpComponentsClientHttpConnector implements + // AutoCloseable and is shared between parameterized test invocations. + @ParameterizedTest(autoCloseArguments = false) @MethodSource("org.springframework.http.client.reactive.ClientHttpConnectorTests#methodsWithConnectors") void basic(ClientHttpConnector connector, HttpMethod method) throws Exception { URI uri = this.server.url("/").uri(); @@ -198,10 +200,11 @@ private void expectRequest(Consumer consumer) { @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) - @ParameterizedTest + // Do not auto-close arguments since HttpComponentsClientHttpConnector implements + // AutoCloseable and is shared between parameterized test invocations. + @ParameterizedTest(autoCloseArguments = false) @MethodSource("org.springframework.http.client.reactive.ClientHttpConnectorTests#connectors") public @interface ParameterizedConnectorTest { - } static List connectors() { diff --git a/spring-web/src/test/java/org/springframework/http/codec/multipart/SynchronossPartHttpMessageReaderTests.java b/spring-web/src/test/java/org/springframework/http/codec/multipart/SynchronossPartHttpMessageReaderTests.java index ba025cbd6b2d..10dbdba63a78 100644 --- a/spring-web/src/test/java/org/springframework/http/codec/multipart/SynchronossPartHttpMessageReaderTests.java +++ b/spring-web/src/test/java/org/springframework/http/codec/multipart/SynchronossPartHttpMessageReaderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -165,37 +165,31 @@ void gh23768() throws IOException { @Test void readTooManyParts() { - testMultipartExceptions(reader -> reader.setMaxParts(1), ex -> { - assertThat(ex) - .isInstanceOf(DecodingException.class) - .hasMessageStartingWith("Failure while parsing part[2]"); - assertThat(ex.getCause()) - .hasMessage("Too many parts (2 allowed)"); - } + testMultipartExceptions(reader -> reader.setMaxParts(1), + ex -> assertThat(ex) + .isInstanceOf(DecodingException.class) + .hasMessageStartingWith("Failure while parsing part[2]") + .hasRootCauseMessage("Too many parts: Part[2] but maxParts=1") ); } @Test void readFilePartTooBig() { - testMultipartExceptions(reader -> reader.setMaxDiskUsagePerPart(5), ex -> { - assertThat(ex) - .isInstanceOf(DecodingException.class) - .hasMessageStartingWith("Failure while parsing part[1]"); - assertThat(ex.getCause()) - .hasMessage("Part[1] exceeded the disk usage limit of 5 bytes"); - } + testMultipartExceptions(reader -> reader.setMaxDiskUsagePerPart(5), + ex -> assertThat(ex) + .isInstanceOf(DecodingException.class) + .hasMessageStartingWith("Failure while parsing part[1]") + .hasRootCauseMessage("Part[1] exceeded the disk usage limit of 5 bytes") ); } @Test void readPartHeadersTooBig() { - testMultipartExceptions(reader -> reader.setMaxInMemorySize(1), ex -> { - assertThat(ex) - .isInstanceOf(DecodingException.class) - .hasMessageStartingWith("Failure while parsing part[1]"); - assertThat(ex.getCause()) - .hasMessage("Part[1] exceeded the in-memory limit of 1 bytes"); - } + testMultipartExceptions(reader -> reader.setMaxInMemorySize(1), + ex -> assertThat(ex) + .isInstanceOf(DecodingException.class) + .hasMessageStartingWith("Failure while parsing part[1]") + .hasRootCauseMessage("Part[1] exceeded the in-memory limit of 1 bytes") ); } diff --git a/spring-web/src/test/java/org/springframework/web/bind/EscapedErrorsTests.java b/spring-web/src/test/java/org/springframework/web/bind/EscapedErrorsTests.java index 80e098ba1301..644086ebf784 100644 --- a/spring-web/src/test/java/org/springframework/web/bind/EscapedErrorsTests.java +++ b/spring-web/src/test/java/org/springframework/web/bind/EscapedErrorsTests.java @@ -83,7 +83,7 @@ public void testEscapedErrors() { FieldError ageError = errors.getFieldError("age"); assertThat("message: <tag>".equals(ageError.getDefaultMessage())).as("Age error message escaped").isTrue(); assertThat("AGE_NOT_SET ".equals(ageError.getCode())).as("Age error code not escaped").isTrue(); - assertThat((new Integer(0)).equals(errors.getFieldValue("age"))).as("Age value not escaped").isTrue(); + assertThat((Integer.valueOf(0)).equals(errors.getFieldValue("age"))).as("Age value not escaped").isTrue(); FieldError ageErrorInList = errors.getFieldErrors("age").get(0); assertThat(ageError.getDefaultMessage().equals(ageErrorInList.getDefaultMessage())).as("Same name error in list").isTrue(); FieldError ageError2 = errors.getFieldErrors("age").get(1); diff --git a/spring-web/src/test/java/org/springframework/web/bind/ServletRequestUtilsTests.java b/spring-web/src/test/java/org/springframework/web/bind/ServletRequestUtilsTests.java index d0f108eb9d7e..00a82790f3b6 100644 --- a/spring-web/src/test/java/org/springframework/web/bind/ServletRequestUtilsTests.java +++ b/spring-web/src/test/java/org/springframework/web/bind/ServletRequestUtilsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -47,7 +47,7 @@ void testIntParameter() throws ServletRequestBindingException { assertThatExceptionOfType(ServletRequestBindingException.class).isThrownBy(() -> ServletRequestUtils.getRequiredIntParameter(request, "param2")); - assertThat(ServletRequestUtils.getIntParameter(request, "param3")).isEqualTo(null); + assertThat(ServletRequestUtils.getIntParameter(request, "param3")).isNull(); assertThat(ServletRequestUtils.getIntParameter(request, "param3", 6)).isEqualTo(6); assertThatExceptionOfType(ServletRequestBindingException.class).isThrownBy(() -> ServletRequestUtils.getRequiredIntParameter(request, "param3")); @@ -66,7 +66,7 @@ void testIntParameters() throws ServletRequestBindingException { int[] array = new int[] {1, 2, 3}; int[] values = ServletRequestUtils.getRequiredIntParameters(request, "param"); - assertThat(3).isEqualTo(values.length); + assertThat(values).hasSize(3); for (int i = 0; i < array.length; i++) { assertThat(array[i]).isEqualTo(values[i]); } @@ -81,7 +81,7 @@ void testLongParameter() throws ServletRequestBindingException { request.addParameter("param2", "e"); request.addParameter("paramEmpty", ""); - assertThat(ServletRequestUtils.getLongParameter(request, "param1")).isEqualTo(new Long(5L)); + assertThat(ServletRequestUtils.getLongParameter(request, "param1")).isEqualTo(Long.valueOf(5L)); assertThat(ServletRequestUtils.getLongParameter(request, "param1", 6L)).isEqualTo(5L); assertThat(ServletRequestUtils.getRequiredIntParameter(request, "param1")).isEqualTo(5L); @@ -89,7 +89,7 @@ void testLongParameter() throws ServletRequestBindingException { assertThatExceptionOfType(ServletRequestBindingException.class).isThrownBy(() -> ServletRequestUtils.getRequiredLongParameter(request, "param2")); - assertThat(ServletRequestUtils.getLongParameter(request, "param3")).isEqualTo(null); + assertThat(ServletRequestUtils.getLongParameter(request, "param3")).isNull(); assertThat(ServletRequestUtils.getLongParameter(request, "param3", 6L)).isEqualTo(6L); assertThatExceptionOfType(ServletRequestBindingException.class).isThrownBy(() -> ServletRequestUtils.getRequiredLongParameter(request, "param3")); @@ -128,7 +128,7 @@ void testFloatParameter() throws ServletRequestBindingException { request.addParameter("param2", "e"); request.addParameter("paramEmpty", ""); - assertThat(ServletRequestUtils.getFloatParameter(request, "param1").equals(new Float(5.5f))).isTrue(); + assertThat(ServletRequestUtils.getFloatParameter(request, "param1")).isEqualTo(Float.valueOf(5.5f)); assertThat(ServletRequestUtils.getFloatParameter(request, "param1", 6.5f) == 5.5f).isTrue(); assertThat(ServletRequestUtils.getRequiredFloatParameter(request, "param1") == 5.5f).isTrue(); @@ -136,7 +136,7 @@ void testFloatParameter() throws ServletRequestBindingException { assertThatExceptionOfType(ServletRequestBindingException.class).isThrownBy(() -> ServletRequestUtils.getRequiredFloatParameter(request, "param2")); - assertThat(ServletRequestUtils.getFloatParameter(request, "param3") == null).isTrue(); + assertThat(ServletRequestUtils.getFloatParameter(request, "param3")).isNull(); assertThat(ServletRequestUtils.getFloatParameter(request, "param3", 6.5f) == 6.5f).isTrue(); assertThatExceptionOfType(ServletRequestBindingException.class).isThrownBy(() -> ServletRequestUtils.getRequiredFloatParameter(request, "param3")); @@ -166,7 +166,7 @@ void testDoubleParameter() throws ServletRequestBindingException { request.addParameter("param2", "e"); request.addParameter("paramEmpty", ""); - assertThat(ServletRequestUtils.getDoubleParameter(request, "param1").equals(new Double(5.5))).isTrue(); + assertThat(ServletRequestUtils.getDoubleParameter(request, "param1")).isEqualTo(Double.valueOf(5.5)); assertThat(ServletRequestUtils.getDoubleParameter(request, "param1", 6.5) == 5.5).isTrue(); assertThat(ServletRequestUtils.getRequiredDoubleParameter(request, "param1") == 5.5).isTrue(); @@ -174,7 +174,7 @@ void testDoubleParameter() throws ServletRequestBindingException { assertThatExceptionOfType(ServletRequestBindingException.class).isThrownBy(() -> ServletRequestUtils.getRequiredDoubleParameter(request, "param2")); - assertThat(ServletRequestUtils.getDoubleParameter(request, "param3") == null).isTrue(); + assertThat(ServletRequestUtils.getDoubleParameter(request, "param3")).isNull(); assertThat(ServletRequestUtils.getDoubleParameter(request, "param3", 6.5) == 6.5).isTrue(); assertThatExceptionOfType(ServletRequestBindingException.class).isThrownBy(() -> ServletRequestUtils.getRequiredDoubleParameter(request, "param3")); @@ -212,7 +212,7 @@ void testBooleanParameter() throws ServletRequestBindingException { assertThat(ServletRequestUtils.getBooleanParameter(request, "param2", true)).isFalse(); assertThat(ServletRequestUtils.getRequiredBooleanParameter(request, "param2")).isFalse(); - assertThat(ServletRequestUtils.getBooleanParameter(request, "param3") == null).isTrue(); + assertThat(ServletRequestUtils.getBooleanParameter(request, "param3")).isNull(); assertThat(ServletRequestUtils.getBooleanParameter(request, "param3", true)).isTrue(); assertThatExceptionOfType(ServletRequestBindingException.class).isThrownBy(() -> ServletRequestUtils.getRequiredBooleanParameter(request, "param3")); @@ -235,14 +235,14 @@ void testBooleanParameters() throws ServletRequestBindingException { boolean[] array = new boolean[] {true, true, false, true, false}; boolean[] values = ServletRequestUtils.getRequiredBooleanParameters(request, "param"); - assertThat(array.length).isEqualTo(values.length); + assertThat(array).hasSameSizeAs(values); for (int i = 0; i < array.length; i++) { assertThat(array[i]).isEqualTo(values[i]); } array = new boolean[] {false, true, false}; values = ServletRequestUtils.getRequiredBooleanParameters(request, "param2"); - assertThat(array.length).isEqualTo(values.length); + assertThat(array).hasSameSizeAs(values); for (int i = 0; i < array.length; i++) { assertThat(array[i]).isEqualTo(values[i]); } diff --git a/spring-web/src/test/java/org/springframework/web/client/HttpMessageConverterExtractorTests.java b/spring-web/src/test/java/org/springframework/web/client/HttpMessageConverterExtractorTests.java index 2374a0d95487..e9d6bd1da382 100644 --- a/spring-web/src/test/java/org/springframework/web/client/HttpMessageConverterExtractorTests.java +++ b/spring-web/src/test/java/org/springframework/web/client/HttpMessageConverterExtractorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -50,7 +50,7 @@ * @author Brian Clozel * @author Sam Brannen */ -public class HttpMessageConverterExtractorTests { +class HttpMessageConverterExtractorTests { @SuppressWarnings("unchecked") private final HttpMessageConverter converter = mock(HttpMessageConverter.class); @@ -61,7 +61,7 @@ public class HttpMessageConverterExtractorTests { @Test - public void constructorPreconditions() { + void constructorPreconditions() { assertThatIllegalArgumentException() .isThrownBy(() -> new HttpMessageConverterExtractor<>(String.class, (List>) null)) .withMessage("'messageConverters' must not be empty"); @@ -71,7 +71,7 @@ public void constructorPreconditions() { } @Test - public void noContent() throws IOException { + void noContent() throws IOException { given(response.getRawStatusCode()).willReturn(HttpStatus.NO_CONTENT.value()); Object result = extractor.extractData(response); @@ -79,7 +79,7 @@ public void noContent() throws IOException { } @Test - public void notModified() throws IOException { + void notModified() throws IOException { given(response.getRawStatusCode()).willReturn(HttpStatus.NOT_MODIFIED.value()); Object result = extractor.extractData(response); @@ -87,7 +87,7 @@ public void notModified() throws IOException { } @Test - public void informational() throws IOException { + void informational() throws IOException { given(response.getRawStatusCode()).willReturn(HttpStatus.CONTINUE.value()); Object result = extractor.extractData(response); @@ -95,7 +95,7 @@ public void informational() throws IOException { } @Test - public void zeroContentLength() throws IOException { + void zeroContentLength() throws IOException { responseHeaders.setContentLength(0); given(response.getRawStatusCode()).willReturn(HttpStatus.OK.value()); given(response.getHeaders()).willReturn(responseHeaders); @@ -105,7 +105,7 @@ public void zeroContentLength() throws IOException { } @Test - public void emptyMessageBody() throws IOException { + void emptyMessageBody() throws IOException { given(response.getRawStatusCode()).willReturn(HttpStatus.OK.value()); given(response.getHeaders()).willReturn(responseHeaders); given(response.getBody()).willReturn(new ByteArrayInputStream("".getBytes())); @@ -115,7 +115,7 @@ public void emptyMessageBody() throws IOException { } @Test // gh-22265 - public void nullMessageBody() throws IOException { + void nullMessageBody() throws IOException { given(response.getRawStatusCode()).willReturn(HttpStatus.OK.value()); given(response.getHeaders()).willReturn(responseHeaders); given(response.getBody()).willReturn(null); @@ -125,7 +125,7 @@ public void nullMessageBody() throws IOException { } @Test - public void normal() throws IOException { + void normal() throws IOException { responseHeaders.setContentType(contentType); String expected = "Foo"; given(response.getRawStatusCode()).willReturn(HttpStatus.OK.value()); @@ -139,7 +139,7 @@ public void normal() throws IOException { } @Test - public void cannotRead() throws IOException { + void cannotRead() throws IOException { responseHeaders.setContentType(contentType); given(response.getRawStatusCode()).willReturn(HttpStatus.OK.value()); given(response.getHeaders()).willReturn(responseHeaders); @@ -150,7 +150,7 @@ public void cannotRead() throws IOException { @Test @SuppressWarnings("unchecked") - public void generics() throws IOException { + void generics() throws IOException { responseHeaders.setContentType(contentType); String expected = "Foo"; ParameterizedTypeReference> reference = new ParameterizedTypeReference>() {}; @@ -170,7 +170,7 @@ public void generics() throws IOException { } @Test // SPR-13592 - public void converterThrowsIOException() throws IOException { + void converterThrowsIOException() throws IOException { responseHeaders.setContentType(contentType); given(response.getRawStatusCode()).willReturn(HttpStatus.OK.value()); given(response.getHeaders()).willReturn(responseHeaders); @@ -183,7 +183,7 @@ public void converterThrowsIOException() throws IOException { } @Test // SPR-13592 - public void converterThrowsHttpMessageNotReadableException() throws IOException { + void converterThrowsHttpMessageNotReadableException() throws IOException { responseHeaders.setContentType(contentType); given(response.getRawStatusCode()).willReturn(HttpStatus.OK.value()); given(response.getHeaders()).willReturn(responseHeaders); @@ -194,4 +194,21 @@ public void converterThrowsHttpMessageNotReadableException() throws IOException .withCauseInstanceOf(HttpMessageNotReadableException.class); } + @Test + void unknownContentTypeExceptionContainsCorrectResponseBody() throws IOException { + responseHeaders.setContentType(contentType); + given(response.getRawStatusCode()).willReturn(HttpStatus.OK.value()); + given(response.getHeaders()).willReturn(responseHeaders); + given(response.getBody()).willReturn(new ByteArrayInputStream("Foobar".getBytes()) { + @Override + public boolean markSupported() { + return false; + } + }); + given(converter.canRead(String.class, contentType)).willReturn(false); + + assertThatExceptionOfType(UnknownContentTypeException.class).isThrownBy(() -> extractor.extractData(response)) + .satisfies(exception -> assertThat(exception.getResponseBodyAsString()).isEqualTo("Foobar")); + } + } diff --git a/spring-web/src/test/java/org/springframework/web/client/MessageBodyClientHttpResponseWrapperTests.java b/spring-web/src/test/java/org/springframework/web/client/MessageBodyClientHttpResponseWrapperTests.java new file mode 100644 index 000000000000..19568910672d --- /dev/null +++ b/spring-web/src/test/java/org/springframework/web/client/MessageBodyClientHttpResponseWrapperTests.java @@ -0,0 +1,56 @@ +/* + * Copyright 2002-2021 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 org.springframework.web.client; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import org.junit.jupiter.api.Test; + +import org.springframework.http.client.ClientHttpResponse; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; + +/** + * Unit tests for {@link MessageBodyClientHttpResponseWrapper}. + * + * @since 5.3.10 + * @author Yin-Jui Liao + */ +class MessageBodyClientHttpResponseWrapperTests { + + private final ClientHttpResponse response = mock(ClientHttpResponse.class); + + private final MessageBodyClientHttpResponseWrapper responseWrapper = new MessageBodyClientHttpResponseWrapper(response); + + + @Test + void messageBodyDoesNotExist() throws Exception { + given(response.getBody()).willReturn(null); + assertThat(responseWrapper.hasEmptyMessageBody()).isTrue(); + } + + @Test + void messageBodyExists() throws Exception { + InputStream stream = new ByteArrayInputStream("content".getBytes()); + given(response.getBody()).willReturn(stream); + assertThat(responseWrapper.hasEmptyMessageBody()).isFalse(); + } + +} diff --git a/spring-web/src/test/java/org/springframework/web/cors/CorsConfigurationTests.java b/spring-web/src/test/java/org/springframework/web/cors/CorsConfigurationTests.java index 256b9631df72..9549902149ec 100644 --- a/spring-web/src/test/java/org/springframework/web/cors/CorsConfigurationTests.java +++ b/spring-web/src/test/java/org/springframework/web/cors/CorsConfigurationTests.java @@ -33,10 +33,10 @@ * @author Sebastien Deleuze * @author Sam Brannen */ -public class CorsConfigurationTests { +class CorsConfigurationTests { @Test - public void setNullValues() { + void setNullValues() { CorsConfiguration config = new CorsConfiguration(); config.setAllowedOrigins(null); assertThat(config.getAllowedOrigins()).isNull(); @@ -55,7 +55,7 @@ public void setNullValues() { } @Test - public void setValues() { + void setValues() { CorsConfiguration config = new CorsConfiguration(); config.addAllowedOrigin("*"); config.addAllowedOriginPattern("http://*.example.com"); @@ -71,11 +71,11 @@ public void setValues() { assertThat(config.getAllowedMethods()).containsExactly("*"); assertThat(config.getExposedHeaders()).containsExactly("*"); assertThat(config.getAllowCredentials()).isTrue(); - assertThat(config.getMaxAge()).isEqualTo(new Long(123)); + assertThat(config.getMaxAge()).isEqualTo(Long.valueOf(123)); } @Test - public void combineWithNull() { + void combineWithNull() { CorsConfiguration config = new CorsConfiguration(); config.setAllowedOrigins(Collections.singletonList("*")); config.combine(null); @@ -84,7 +84,7 @@ public void combineWithNull() { } @Test - public void combineWithNullProperties() { + void combineWithNullProperties() { CorsConfiguration config = new CorsConfiguration(); config.addAllowedOrigin("*"); config.setAllowedOriginPatterns(Collections.singletonList("http://*.example.com")); @@ -103,12 +103,12 @@ public void combineWithNullProperties() { assertThat(config.getAllowedHeaders()).containsExactly("header1"); assertThat(config.getExposedHeaders()).containsExactly("header3"); assertThat(config.getAllowedMethods()).containsExactly(HttpMethod.GET.name()); - assertThat(config.getMaxAge()).isEqualTo(new Long(123)); + assertThat(config.getMaxAge()).isEqualTo(Long.valueOf(123)); assertThat(config.getAllowCredentials()).isTrue(); } @Test // SPR-15772 - public void combineWithDefaultPermitValues() { + void combineWithDefaultPermitValues() { CorsConfiguration config = new CorsConfiguration().applyPermitDefaultValues(); CorsConfiguration other = new CorsConfiguration(); other.addAllowedOrigin("https://domain.com"); @@ -147,7 +147,7 @@ public void combineWithDefaultPermitValues() { } @Test - public void combinePatternWithDefaultPermitValues() { + void combinePatternWithDefaultPermitValues() { CorsConfiguration config = new CorsConfiguration().applyPermitDefaultValues(); CorsConfiguration other = new CorsConfiguration(); other.addAllowedOriginPattern("http://*.com"); @@ -164,7 +164,7 @@ public void combinePatternWithDefaultPermitValues() { } @Test - public void combinePatternWithDefaultPermitValuesAndCustomOrigin() { + void combinePatternWithDefaultPermitValuesAndCustomOrigin() { CorsConfiguration config = new CorsConfiguration().applyPermitDefaultValues(); config.setAllowedOrigins(Collections.singletonList("https://domain.com")); @@ -183,7 +183,7 @@ public void combinePatternWithDefaultPermitValuesAndCustomOrigin() { } @Test - public void combineWithAsteriskWildCard() { + void combineWithAsteriskWildCard() { CorsConfiguration config = new CorsConfiguration(); config.addAllowedOrigin("*"); config.addAllowedHeader("*"); @@ -219,7 +219,7 @@ public void combineWithAsteriskWildCard() { } @Test // SPR-14792 - public void combineWithDuplicatedElements() { + void combineWithDuplicatedElements() { CorsConfiguration config = new CorsConfiguration(); config.addAllowedOrigin("https://domain1.com"); config.addAllowedOrigin("https://domain2.com"); @@ -249,7 +249,7 @@ public void combineWithDuplicatedElements() { } @Test - public void combine() { + void combine() { CorsConfiguration config = new CorsConfiguration(); config.addAllowedOrigin("https://domain1.com"); config.addAllowedOriginPattern("http://*.domain1.com"); @@ -274,14 +274,14 @@ public void combine() { assertThat(config.getAllowedHeaders()).containsExactly("header1", "header2"); assertThat(config.getExposedHeaders()).containsExactly("header3", "header4"); assertThat(config.getAllowedMethods()).containsExactly(HttpMethod.GET.name(), HttpMethod.PUT.name()); - assertThat(config.getMaxAge()).isEqualTo(new Long(456)); + assertThat(config.getMaxAge()).isEqualTo(Long.valueOf(456)); assertThat(config).isNotNull(); assertThat(config.getAllowCredentials()).isFalse(); assertThat(config.getAllowedOriginPatterns()).containsExactly("http://*.domain1.com", "http://*.domain2.com"); } @Test - public void checkOriginAllowed() { + void checkOriginAllowed() { // "*" matches CorsConfiguration config = new CorsConfiguration(); config.addAllowedOrigin("*"); @@ -306,7 +306,7 @@ public void checkOriginAllowed() { } @Test - public void checkOriginNotAllowed() { + void checkOriginNotAllowed() { CorsConfiguration config = new CorsConfiguration(); assertThat(config.checkOrigin(null)).isNull(); assertThat(config.checkOrigin("https://domain.com")).isNull(); @@ -322,7 +322,7 @@ public void checkOriginNotAllowed() { } @Test - public void checkOriginPatternAllowed() { + void checkOriginPatternAllowed() { CorsConfiguration config = new CorsConfiguration(); assertThat(config.checkOrigin("https://domain.com")).isNull(); @@ -349,7 +349,7 @@ public void checkOriginPatternAllowed() { } @Test - public void checkOriginPatternNotAllowed() { + void checkOriginPatternNotAllowed() { CorsConfiguration config = new CorsConfiguration(); assertThat(config.checkOrigin(null)).isNull(); assertThat(config.checkOrigin("https://domain.com")).isNull(); @@ -367,7 +367,7 @@ public void checkOriginPatternNotAllowed() { } @Test - public void checkMethodAllowed() { + void checkMethodAllowed() { CorsConfiguration config = new CorsConfiguration(); assertThat(config.checkHttpMethod(HttpMethod.GET)).containsExactly(HttpMethod.GET, HttpMethod.HEAD); @@ -380,7 +380,7 @@ public void checkMethodAllowed() { } @Test - public void checkMethodNotAllowed() { + void checkMethodNotAllowed() { CorsConfiguration config = new CorsConfiguration(); assertThat(config.checkHttpMethod(null)).isNull(); assertThat(config.checkHttpMethod(HttpMethod.DELETE)).isNull(); @@ -390,7 +390,7 @@ public void checkMethodNotAllowed() { } @Test - public void checkHeadersAllowed() { + void checkHeadersAllowed() { CorsConfiguration config = new CorsConfiguration(); assertThat(config.checkHeaders(Collections.emptyList())).isEqualTo(Collections.emptyList()); @@ -403,7 +403,7 @@ public void checkHeadersAllowed() { } @Test - public void checkHeadersNotAllowed() { + void checkHeadersNotAllowed() { CorsConfiguration config = new CorsConfiguration(); assertThat(config.checkHeaders(null)).isNull(); assertThat(config.checkHeaders(Collections.singletonList("header1"))).isNull(); @@ -417,7 +417,7 @@ public void checkHeadersNotAllowed() { } @Test // SPR-15772 - public void changePermitDefaultValues() { + void changePermitDefaultValues() { CorsConfiguration config = new CorsConfiguration().applyPermitDefaultValues(); config.addAllowedOrigin("https://domain.com"); config.addAllowedHeader("header1"); @@ -429,7 +429,7 @@ public void changePermitDefaultValues() { } @Test - public void permitDefaultDoesntSetOriginWhenPatternPresent() { + void permitDefaultDoesntSetOriginWhenPatternPresent() { CorsConfiguration config = new CorsConfiguration(); config.addAllowedOriginPattern("http://*.com"); config = config.applyPermitDefaultValues(); diff --git a/spring-web/src/test/java/org/springframework/web/method/support/CompositeUriComponentsContributorTests.java b/spring-web/src/test/java/org/springframework/web/method/support/CompositeUriComponentsContributorTests.java index a9030b3ab796..1b698914abaa 100644 --- a/spring-web/src/test/java/org/springframework/web/method/support/CompositeUriComponentsContributorTests.java +++ b/spring-web/src/test/java/org/springframework/web/method/support/CompositeUriComponentsContributorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -32,30 +32,33 @@ import static org.assertj.core.api.Assertions.assertThat; /** - * Unit tests for - * {@link org.springframework.web.method.support.CompositeUriComponentsContributor}. + * Unit tests for {@link CompositeUriComponentsContributor}. * * @author Rossen Stoyanchev + * @author Sam Brannen */ -public class CompositeUriComponentsContributorTests { - +class CompositeUriComponentsContributorTests { @Test - public void supportsParameter() { - + void supportsParameter() { List resolvers = new ArrayList<>(); resolvers.add(new RequestParamMethodArgumentResolver(false)); resolvers.add(new RequestHeaderMethodArgumentResolver(null)); resolvers.add(new RequestParamMethodArgumentResolver(true)); - Method method = ClassUtils.getMethod(this.getClass(), "handleRequest", String.class, String.class, String.class); - CompositeUriComponentsContributor contributor = new CompositeUriComponentsContributor(resolvers); + Method method = ClassUtils.getMethod(this.getClass(), "handleRequest", String.class, String.class, String.class); assertThat(contributor.supportsParameter(new MethodParameter(method, 0))).isTrue(); assertThat(contributor.supportsParameter(new MethodParameter(method, 1))).isTrue(); assertThat(contributor.supportsParameter(new MethodParameter(method, 2))).isFalse(); } + @Test + void hasContributors() { + assertThat(new CompositeUriComponentsContributor().hasContributors()).isFalse(); + assertThat(new CompositeUriComponentsContributor(new RequestParamMethodArgumentResolver(true)).hasContributors()).isTrue(); + } + public void handleRequest(@RequestParam String p1, String p2, @RequestHeader String h) { } diff --git a/spring-web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java b/spring-web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java index 52623dacc9af..d6d971c4ed5a 100644 --- a/spring-web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java +++ b/spring-web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java @@ -378,7 +378,7 @@ void fromHttpRequest() { @ParameterizedTest // gh-17368, gh-27097 @ValueSource(strings = {"https", "wss"}) - void fromHttpRequestResetsPortBeforeSettingIt(String protocol) { + void fromHttpRequestResetsPort443(String protocol) { MockHttpServletRequest request = new MockHttpServletRequest(); request.addHeader("X-Forwarded-Proto", protocol); request.addHeader("X-Forwarded-Host", "84.198.58.199"); @@ -397,6 +397,27 @@ void fromHttpRequestResetsPortBeforeSettingIt(String protocol) { assertThat(result.getPath()).isEqualTo("/rest/mobile/users/1"); } + @ParameterizedTest // gh-27097 + @ValueSource(strings = {"http", "ws"}) + void fromHttpRequestResetsPort80(String protocol) { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addHeader("X-Forwarded-Proto", protocol); + request.addHeader("X-Forwarded-Host", "84.198.58.199"); + request.addHeader("X-Forwarded-Port", 80); + request.setScheme("http"); + request.setServerName("example.com"); + request.setServerPort(80); + request.setRequestURI("/path"); + + HttpRequest httpRequest = new ServletServerHttpRequest(request); + UriComponents result = UriComponentsBuilder.fromHttpRequest(httpRequest).build(); + + assertThat(result.getScheme()).isEqualTo(protocol); + assertThat(result.getHost()).isEqualTo("84.198.58.199"); + assertThat(result.getPort()).isEqualTo(-1); + assertThat(result.getPath()).isEqualTo("/path"); + } + @Test // SPR-14761 void fromHttpRequestWithForwardedIPv4Host() { MockHttpServletRequest request = new MockHttpServletRequest(); diff --git a/spring-web/src/test/java/org/springframework/web/util/UrlPathHelperTests.java b/spring-web/src/test/java/org/springframework/web/util/UrlPathHelperTests.java index 0aea5a0b51d9..e3281e55273f 100644 --- a/spring-web/src/test/java/org/springframework/web/util/UrlPathHelperTests.java +++ b/spring-web/src/test/java/org/springframework/web/util/UrlPathHelperTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -22,6 +22,7 @@ import org.springframework.web.testfixture.servlet.MockHttpServletRequest; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; /** * Unit tests for {@link UrlPathHelper}. @@ -30,7 +31,7 @@ * @author Juergen Hoeller * @author Costin Leau */ -public class UrlPathHelperTests { +class UrlPathHelperTests { private static final String WEBSPHERE_URI_ATTRIBUTE = "com.ibm.websphere.servlet.uri_non_decoded"; @@ -40,7 +41,7 @@ public class UrlPathHelperTests { @Test - public void getPathWithinApplication() { + void getPathWithinApplication() { request.setContextPath("/petclinic"); request.setRequestURI("/petclinic/welcome.html"); @@ -48,7 +49,7 @@ public void getPathWithinApplication() { } @Test - public void getPathWithinApplicationForRootWithNoLeadingSlash() { + void getPathWithinApplicationForRootWithNoLeadingSlash() { request.setContextPath("/petclinic"); request.setRequestURI("/petclinic"); @@ -56,7 +57,7 @@ public void getPathWithinApplicationForRootWithNoLeadingSlash() { } @Test - public void getPathWithinApplicationForSlashContextPath() { + void getPathWithinApplicationForSlashContextPath() { request.setContextPath("/"); request.setRequestURI("/welcome.html"); @@ -64,7 +65,7 @@ public void getPathWithinApplicationForSlashContextPath() { } @Test - public void getPathWithinServlet() { + void getPathWithinServlet() { request.setContextPath("/petclinic"); request.setServletPath("/main"); request.setRequestURI("/petclinic/main/welcome.html"); @@ -73,7 +74,7 @@ public void getPathWithinServlet() { } @Test - public void alwaysUseFullPath() { + void alwaysUseFullPath() { helper.setAlwaysUseFullPath(true); request.setContextPath("/petclinic"); request.setServletPath("/main"); @@ -83,7 +84,7 @@ public void alwaysUseFullPath() { } @Test // SPR-11101 - public void getPathWithinServletWithoutUrlDecoding() { + void getPathWithinServletWithoutUrlDecoding() { request.setContextPath("/SPR-11101"); request.setServletPath("/test_url_decoding/a/b"); request.setRequestURI("/test_url_decoding/a%2Fb"); @@ -95,7 +96,7 @@ public void getPathWithinServletWithoutUrlDecoding() { } @Test - public void getRequestUri() { + void getRequestUri() { request.setRequestURI("/welcome.html"); assertThat(helper.getRequestUri(request)).isEqualTo("/welcome.html"); @@ -110,7 +111,7 @@ public void getRequestUri() { } @Test - public void getRequestRemoveSemicolonContent() { + void getRequestRemoveSemicolonContent() { helper.setRemoveSemicolonContent(true); request.setRequestURI("/foo;f=F;o=O;o=O/bar;b=B;a=A;r=R"); assertThat(helper.getRequestUri(request)).isEqualTo("/foo/bar"); @@ -125,7 +126,7 @@ public void getRequestRemoveSemicolonContent() { } @Test - public void getRequestKeepSemicolonContent() { + void getRequestKeepSemicolonContent() { helper.setRemoveSemicolonContent(false); testKeepSemicolonContent("/foo;a=b;c=d", "/foo;a=b;c=d"); @@ -144,7 +145,7 @@ private void testKeepSemicolonContent(String requestUri, String expectedPath) { } @Test - public void getLookupPathWithSemicolonContent() { + void getLookupPathWithSemicolonContent() { helper.setRemoveSemicolonContent(false); request.setContextPath("/petclinic"); @@ -155,7 +156,7 @@ public void getLookupPathWithSemicolonContent() { } @Test - public void getLookupPathWithSemicolonContentAndNullPathInfo() { + void getLookupPathWithSemicolonContentAndNullPathInfo() { helper.setRemoveSemicolonContent(false); request.setContextPath("/petclinic"); @@ -165,6 +166,27 @@ public void getLookupPathWithSemicolonContentAndNullPathInfo() { assertThat(helper.getLookupPathForRequest(request)).isEqualTo("/welcome.html;c=d"); } + @Test // gh-27303 + void defaultInstanceReadOnlyBehavior() { + UrlPathHelper helper = UrlPathHelper.defaultInstance; + + assertThatIllegalArgumentException() + .isThrownBy(() -> helper.setAlwaysUseFullPath(true)) + .withMessage("This instance cannot be modified"); + assertThatIllegalArgumentException() + .isThrownBy(() -> helper.setUrlDecode(true)) + .withMessage("This instance cannot be modified"); + assertThatIllegalArgumentException() + .isThrownBy(() -> helper.setRemoveSemicolonContent(true)) + .withMessage("This instance cannot be modified"); + assertThatIllegalArgumentException() + .isThrownBy(() -> helper.setDefaultEncoding("UTF-8")) + .withMessage("This instance cannot be modified"); + + assertThat(helper.isUrlDecode()).isTrue(); + assertThat(helper.shouldRemoveSemicolonContent()).isTrue(); + } + // // suite of tests root requests for default servlets (SRV 11.2) on Websphere vs Tomcat and other containers @@ -177,7 +199,7 @@ public void getLookupPathWithSemicolonContentAndNullPathInfo() { // @Test - public void tomcatDefaultServletRoot() { + void tomcatDefaultServletRoot() { request.setContextPath("/test"); request.setServletPath("/"); request.setPathInfo(null); @@ -186,7 +208,7 @@ public void tomcatDefaultServletRoot() { } @Test - public void tomcatDefaultServletFile() { + void tomcatDefaultServletFile() { request.setContextPath("/test"); request.setServletPath("/foo"); request.setPathInfo(null); @@ -196,7 +218,7 @@ public void tomcatDefaultServletFile() { } @Test - public void tomcatDefaultServletFolder() { + void tomcatDefaultServletFolder() { request.setContextPath("/test"); request.setServletPath("/foo/"); request.setPathInfo(null); @@ -206,7 +228,7 @@ public void tomcatDefaultServletFolder() { } @Test //SPR-12372, SPR-13455 - public void removeDuplicateSlashesInPath() { + void removeDuplicateSlashesInPath() { request.setContextPath("/SPR-12372"); request.setPathInfo(null); request.setServletPath("/foo/bar/"); @@ -227,7 +249,7 @@ public void removeDuplicateSlashesInPath() { } @Test - public void wasDefaultServletRoot() { + void wasDefaultServletRoot() { request.setContextPath("/test"); request.setPathInfo("/"); request.setServletPath(""); @@ -238,13 +260,13 @@ public void wasDefaultServletRoot() { } @Test - public void wasDefaultServletRootWithCompliantSetting() { + void wasDefaultServletRootWithCompliantSetting() { request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/"); tomcatDefaultServletRoot(); } @Test - public void wasDefaultServletFile() { + void wasDefaultServletFile() { request.setContextPath("/test"); request.setPathInfo("/foo"); request.setServletPath(""); @@ -255,13 +277,13 @@ public void wasDefaultServletFile() { } @Test - public void wasDefaultServletFileWithCompliantSetting() { + void wasDefaultServletFileWithCompliantSetting() { request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/foo"); tomcatDefaultServletFile(); } @Test - public void wasDefaultServletFolder() { + void wasDefaultServletFolder() { request.setContextPath("/test"); request.setPathInfo("/foo/"); request.setServletPath(""); @@ -272,7 +294,7 @@ public void wasDefaultServletFolder() { } @Test - public void wasDefaultServletFolderWithCompliantSetting() { + void wasDefaultServletFolderWithCompliantSetting() { UrlPathHelper.websphereComplianceFlag = true; try { request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/foo/"); @@ -289,7 +311,7 @@ public void wasDefaultServletFolderWithCompliantSetting() { // @Test - public void tomcatCasualServletRoot() { + void tomcatCasualServletRoot() { request.setContextPath("/test"); request.setPathInfo("/"); request.setServletPath("/foo"); @@ -299,9 +321,9 @@ public void tomcatCasualServletRoot() { } @Disabled - // test the root mapping for /foo/* w/o a trailing slash - //foo @Test - public void tomcatCasualServletRootWithMissingSlash() { + // test the root mapping for /foo/* w/o a trailing slash - //foo + void tomcatCasualServletRootWithMissingSlash() { request.setContextPath("/test"); request.setPathInfo(null); request.setServletPath("/foo"); @@ -311,7 +333,7 @@ public void tomcatCasualServletRootWithMissingSlash() { } @Test - public void tomcatCasualServletFile() { + void tomcatCasualServletFile() { request.setContextPath("/test"); request.setPathInfo("/foo"); request.setServletPath("/foo"); @@ -321,7 +343,7 @@ public void tomcatCasualServletFile() { } @Test - public void tomcatCasualServletFolder() { + void tomcatCasualServletFolder() { request.setContextPath("/test"); request.setPathInfo("/foo/"); request.setServletPath("/foo"); @@ -331,7 +353,7 @@ public void tomcatCasualServletFolder() { } @Test - public void wasCasualServletRoot() { + void wasCasualServletRoot() { request.setContextPath("/test"); request.setPathInfo(null); request.setServletPath("/foo/"); @@ -342,15 +364,15 @@ public void wasCasualServletRoot() { } @Test - public void wasCasualServletRootWithCompliantSetting() { + void wasCasualServletRootWithCompliantSetting() { request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/foo/"); tomcatCasualServletRoot(); } @Disabled - // test the root mapping for /foo/* w/o a trailing slash - //foo @Test - public void wasCasualServletRootWithMissingSlash() { + // test the root mapping for /foo/* w/o a trailing slash - //foo + void wasCasualServletRootWithMissingSlash() { request.setContextPath("/test"); request.setPathInfo(null); request.setServletPath("/foo"); @@ -362,13 +384,13 @@ public void wasCasualServletRootWithMissingSlash() { @Disabled @Test - public void wasCasualServletRootWithMissingSlashWithCompliantSetting() { + void wasCasualServletRootWithMissingSlashWithCompliantSetting() { request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/foo"); tomcatCasualServletRootWithMissingSlash(); } @Test - public void wasCasualServletFile() { + void wasCasualServletFile() { request.setContextPath("/test"); request.setPathInfo("/foo"); request.setServletPath("/foo"); @@ -379,13 +401,13 @@ public void wasCasualServletFile() { } @Test - public void wasCasualServletFileWithCompliantSetting() { + void wasCasualServletFileWithCompliantSetting() { request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/foo/foo"); tomcatCasualServletFile(); } @Test - public void wasCasualServletFolder() { + void wasCasualServletFolder() { request.setContextPath("/test"); request.setPathInfo("/foo/"); request.setServletPath("/foo"); @@ -396,33 +418,33 @@ public void wasCasualServletFolder() { } @Test - public void wasCasualServletFolderWithCompliantSetting() { + void wasCasualServletFolderWithCompliantSetting() { request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/test/foo/foo/"); tomcatCasualServletFolder(); } @Test - public void getOriginatingRequestUri() { + void getOriginatingRequestUri() { request.setAttribute(WebUtils.FORWARD_REQUEST_URI_ATTRIBUTE, "/path"); request.setRequestURI("/forwarded"); assertThat(helper.getOriginatingRequestUri(request)).isEqualTo("/path"); } @Test - public void getOriginatingRequestUriWebsphere() { + void getOriginatingRequestUriWebsphere() { request.setAttribute(WEBSPHERE_URI_ATTRIBUTE, "/path"); request.setRequestURI("/forwarded"); assertThat(helper.getOriginatingRequestUri(request)).isEqualTo("/path"); } @Test - public void getOriginatingRequestUriDefault() { + void getOriginatingRequestUriDefault() { request.setRequestURI("/forwarded"); assertThat(helper.getOriginatingRequestUri(request)).isEqualTo("/forwarded"); } @Test - public void getOriginatingQueryString() { + void getOriginatingQueryString() { request.setQueryString("forward=on"); request.setAttribute(WebUtils.FORWARD_REQUEST_URI_ATTRIBUTE, "/path"); request.setAttribute(WebUtils.FORWARD_QUERY_STRING_ATTRIBUTE, "original=on"); @@ -430,13 +452,13 @@ public void getOriginatingQueryString() { } @Test - public void getOriginatingQueryStringNotPresent() { + void getOriginatingQueryStringNotPresent() { request.setQueryString("forward=true"); assertThat(this.helper.getOriginatingQueryString(request)).isEqualTo("forward=true"); } @Test - public void getOriginatingQueryStringIsNull() { + void getOriginatingQueryStringIsNull() { request.setQueryString("forward=true"); request.setAttribute(WebUtils.FORWARD_REQUEST_URI_ATTRIBUTE, "/path"); assertThat(this.helper.getOriginatingQueryString(request)).isNull(); diff --git a/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockHttpServletResponse.java b/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockHttpServletResponse.java index f3215a88b253..4a343c8344c7 100644 --- a/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockHttpServletResponse.java +++ b/spring-web/src/testFixtures/java/org/springframework/web/testfixture/servlet/MockHttpServletResponse.java @@ -80,10 +80,16 @@ public class MockHttpServletResponse implements HttpServletResponse { private boolean writerAccessAllowed = true; - @Nullable - private String characterEncoding = WebUtils.DEFAULT_CHARACTER_ENCODING; + private String defaultCharacterEncoding = WebUtils.DEFAULT_CHARACTER_ENCODING; - private boolean charset = false; + private String characterEncoding = this.defaultCharacterEncoding; + + /** + * {@code true} if the character encoding has been explicitly set through + * {@link HttpServletResponse} methods or through a {@code charset} parameter + * on the {@code Content-Type}. + */ + private boolean characterEncodingSet = false; private final ByteArrayOutputStream content = new ByteArrayOutputStream(1024); @@ -117,6 +123,11 @@ public class MockHttpServletResponse implements HttpServletResponse { @Nullable private String errorMessage; + + //--------------------------------------------------------------------- + // Properties for MockRequestDispatcher + //--------------------------------------------------------------------- + @Nullable private String forwardedUrl; @@ -158,25 +169,54 @@ public boolean isWriterAccessAllowed() { } /** - * Return whether the character encoding has been set. - *

        If {@code false}, {@link #getCharacterEncoding()} will return a default encoding value. + * Set the default character encoding for the response. + *

        If this method is not invoked, {@code ISO-8859-1} will be used as the + * default character encoding. + *

        If the {@linkplain #getCharacterEncoding() character encoding} for the + * response has not already been explicitly set via {@link #setCharacterEncoding(String)} + * or {@link #setContentType(String)}, the character encoding for the response + * will be set to the supplied default character encoding. + * @param characterEncoding the default character encoding + * @since 5.3.10 + * @see #setCharacterEncoding(String) + * @see #setContentType(String) + */ + public void setDefaultCharacterEncoding(String characterEncoding) { + Assert.notNull(characterEncoding, "'characterEncoding' must not be null"); + this.defaultCharacterEncoding = characterEncoding; + if (!this.characterEncodingSet) { + this.characterEncoding = characterEncoding; + } + } + + /** + * Determine whether the character encoding has been explicitly set through + * {@link HttpServletResponse} methods or through a {@code charset} parameter + * on the {@code Content-Type}. + *

        If {@code false}, {@link #getCharacterEncoding()} will return the + * {@linkplain #setDefaultCharacterEncoding(String) default character encoding}. */ public boolean isCharset() { - return this.charset; + return this.characterEncodingSet; } @Override public void setCharacterEncoding(String characterEncoding) { - this.characterEncoding = characterEncoding; - this.charset = true; + setExplicitCharacterEncoding(characterEncoding); updateContentTypePropertyAndHeader(); } + private void setExplicitCharacterEncoding(String characterEncoding) { + Assert.notNull(characterEncoding, "'characterEncoding' must not be null"); + this.characterEncoding = characterEncoding; + this.characterEncodingSet = true; + } + private void updateContentTypePropertyAndHeader() { if (this.contentType != null) { String value = this.contentType; - if (this.charset && !this.contentType.toLowerCase().contains(CHARSET_PREFIX)) { - value = value + ';' + CHARSET_PREFIX + this.characterEncoding; + if (this.characterEncodingSet && !value.toLowerCase().contains(CHARSET_PREFIX)) { + value += ';' + CHARSET_PREFIX + getCharacterEncoding(); this.contentType = value; } doAddHeaderValue(HttpHeaders.CONTENT_TYPE, value, true); @@ -184,7 +224,6 @@ private void updateContentTypePropertyAndHeader() { } @Override - @Nullable public String getCharacterEncoding() { return this.characterEncoding; } @@ -199,9 +238,7 @@ public ServletOutputStream getOutputStream() { public PrintWriter getWriter() throws UnsupportedEncodingException { Assert.state(this.writerAccessAllowed, "Writer access not allowed"); if (this.writer == null) { - Writer targetWriter = (this.characterEncoding != null ? - new OutputStreamWriter(this.content, this.characterEncoding) : - new OutputStreamWriter(this.content)); + Writer targetWriter = new OutputStreamWriter(this.content, getCharacterEncoding()); this.writer = new ResponsePrintWriter(targetWriter); } return this.writer; @@ -215,14 +252,17 @@ public byte[] getContentAsByteArray() { * Get the content of the response body as a {@code String}, using the charset * specified for the response by the application, either through * {@link HttpServletResponse} methods or through a charset parameter on the - * {@code Content-Type}. + * {@code Content-Type}. If no charset has been explicitly defined, the + * {@linkplain #setDefaultCharacterEncoding(String) default character encoding} + * will be used. * @return the content as a {@code String} * @throws UnsupportedEncodingException if the character encoding is not supported * @see #getContentAsString(Charset) + * @see #setCharacterEncoding(String) + * @see #setContentType(String) */ public String getContentAsString() throws UnsupportedEncodingException { - return (this.characterEncoding != null ? - this.content.toString(this.characterEncoding) : this.content.toString()); + return this.content.toString(getCharacterEncoding()); } /** @@ -235,11 +275,12 @@ public String getContentAsString() throws UnsupportedEncodingException { * @throws UnsupportedEncodingException if the character encoding is not supported * @since 5.2 * @see #getContentAsString() + * @see #setCharacterEncoding(String) + * @see #setContentType(String) */ public String getContentAsString(Charset fallbackCharset) throws UnsupportedEncodingException { - return (isCharset() && this.characterEncoding != null ? - this.content.toString(this.characterEncoding) : - this.content.toString(fallbackCharset.name())); + String charsetName = (this.characterEncodingSet ? getCharacterEncoding() : fallbackCharset.name()); + return this.content.toString(charsetName); } @Override @@ -269,16 +310,14 @@ public void setContentType(@Nullable String contentType) { try { MediaType mediaType = MediaType.parseMediaType(contentType); if (mediaType.getCharset() != null) { - this.characterEncoding = mediaType.getCharset().name(); - this.charset = true; + setExplicitCharacterEncoding(mediaType.getCharset().name()); } } catch (Exception ex) { // Try to get charset value anyway int charsetIndex = contentType.toLowerCase().indexOf(CHARSET_PREFIX); if (charsetIndex != -1) { - this.characterEncoding = contentType.substring(charsetIndex + CHARSET_PREFIX.length()); - this.charset = true; + setExplicitCharacterEncoding(contentType.substring(charsetIndex + CHARSET_PREFIX.length())); } } updateContentTypePropertyAndHeader(); @@ -331,8 +370,8 @@ public boolean isCommitted() { @Override public void reset() { resetBuffer(); - this.characterEncoding = null; - this.charset = false; + this.characterEncoding = this.defaultCharacterEncoding; + this.characterEncodingSet = false; this.contentLength = 0; this.contentType = null; this.locale = Locale.getDefault(); @@ -343,7 +382,10 @@ public void reset() { } @Override - public void setLocale(Locale locale) { + public void setLocale(@Nullable Locale locale) { + // Although the Javadoc for javax.servlet.ServletResponse.setLocale(Locale) does not + // state how a null value for the supplied Locale should be handled, both Tomcat and + // Jetty simply ignore a null value. So we do the same here. if (locale == null) { return; } diff --git a/spring-webflux/spring-webflux.gradle b/spring-webflux/spring-webflux.gradle index c793b31804ea..b762e09c5cb6 100644 --- a/spring-webflux/spring-webflux.gradle +++ b/spring-webflux/spring-webflux.gradle @@ -3,11 +3,10 @@ description = "Spring WebFlux" apply plugin: "kotlin" dependencies { - compile(project(":spring-beans")) - compile(project(":spring-core")) - compile(project(":spring-web")) - compile("io.projectreactor:reactor-core") - compileOnly(project(":kotlin-coroutines")) + api(project(":spring-beans")) + api(project(":spring-core")) + api(project(":spring-web")) + api("io.projectreactor:reactor-core") optional(project(":spring-context")) optional(project(":spring-context-support")) // for FreeMarker support optional("javax.servlet:javax.servlet-api") @@ -27,35 +26,34 @@ dependencies { optional("org.jetbrains.kotlin:kotlin-stdlib") optional("com.google.protobuf:protobuf-java-util") optional("org.jetbrains.kotlinx:kotlinx-coroutines-reactor") - testCompile(project(":kotlin-coroutines")) - testCompile(testFixtures(project(":spring-beans"))) - testCompile(testFixtures(project(":spring-core"))) - testCompile(testFixtures(project(":spring-web"))) - testCompile("javax.xml.bind:jaxb-api") - testCompile("com.fasterxml:aalto-xml") - testCompile("org.hibernate:hibernate-validator") - testCompile("javax.validation:validation-api") - testCompile("io.reactivex.rxjava3:rxjava") - testCompile("io.projectreactor:reactor-test") - testCompile("io.undertow:undertow-core") - testCompile("org.apache.tomcat.embed:tomcat-embed-core") - testCompile("org.apache.tomcat:tomcat-util") - testCompile("org.eclipse.jetty:jetty-server") - testCompile("org.eclipse.jetty:jetty-servlet") - testCompile("org.eclipse.jetty:jetty-reactive-httpclient") - testCompile('org.apache.httpcomponents.client5:httpclient5') - testCompile('org.apache.httpcomponents.core5:httpcore5-reactive') - testCompile("com.squareup.okhttp3:mockwebserver") - testCompile("org.jetbrains.kotlin:kotlin-script-runtime") - testRuntime("org.jetbrains.kotlin:kotlin-scripting-jsr223") - testRuntime("org.jruby:jruby") - testRuntime("org.python:jython-standalone") - testRuntime("org.synchronoss.cloud:nio-multipart-parser") - testRuntime("org.webjars:underscorejs") - testRuntime("org.glassfish:javax.el") - testRuntime("com.sun.xml.bind:jaxb-core") - testRuntime("com.sun.xml.bind:jaxb-impl") - testRuntime("com.sun.activation:javax.activation") + testImplementation(testFixtures(project(":spring-beans"))) + testImplementation(testFixtures(project(":spring-core"))) + testImplementation(testFixtures(project(":spring-web"))) + testImplementation("javax.xml.bind:jaxb-api") + testImplementation("com.fasterxml:aalto-xml") + testImplementation("org.hibernate:hibernate-validator") + testImplementation("javax.validation:validation-api") + testImplementation("io.reactivex.rxjava3:rxjava") + testImplementation("io.projectreactor:reactor-test") + testImplementation("io.undertow:undertow-core") + testImplementation("org.apache.tomcat.embed:tomcat-embed-core") + testImplementation("org.apache.tomcat:tomcat-util") + testImplementation("org.eclipse.jetty:jetty-server") + testImplementation("org.eclipse.jetty:jetty-servlet") + testImplementation("org.eclipse.jetty:jetty-reactive-httpclient") + testImplementation('org.apache.httpcomponents.client5:httpclient5') + testImplementation('org.apache.httpcomponents.core5:httpcore5-reactive') + testImplementation("com.squareup.okhttp3:mockwebserver") + testImplementation("org.jetbrains.kotlin:kotlin-script-runtime") + testRuntimeOnly("org.jetbrains.kotlin:kotlin-scripting-jsr223") + testRuntimeOnly("org.jruby:jruby") + testRuntimeOnly("org.python:jython-standalone") + testRuntimeOnly("org.synchronoss.cloud:nio-multipart-parser") + testRuntimeOnly("org.webjars:underscorejs") + testRuntimeOnly("org.glassfish:javax.el") + testRuntimeOnly("com.sun.xml.bind:jaxb-core") + testRuntimeOnly("com.sun.xml.bind:jaxb-impl") + testRuntimeOnly("com.sun.activation:javax.activation") } test { diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ClientRequest.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ClientRequest.java index 9e7cc31ba6b4..2b61dba1836a 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ClientRequest.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ClientRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -125,16 +125,17 @@ default Optional attribute(String name) { // Static builder methods /** - * Create a builder with the method, URI, headers, and cookies of the given request. - * @param other the request to copy the method, URI, headers, and cookies from - * @return the created builder + * Create a builder initialized with the HTTP method, url, headers, cookies, + * attributes, and body of the given request. + * @param other the request to copy from + * @return the builder instance */ static Builder from(ClientRequest other) { return new DefaultClientRequestBuilder(other); } /** - * Create a builder with the given method and url. + * Create a builder with the given HTTP method and url. * @param method the HTTP method (GET, POST, etc) * @param url the url (as a URI instance) * @return the created builder @@ -146,7 +147,7 @@ static Builder method(HttpMethod method, URI url) { } /** - * Create a request builder with the given method and url. + * Create a request builder with the given HTTP method and url. * @param method the HTTP method (GET, POST, etc) * @param url the url (as a URI instance) * @return the created builder diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ClientResponse.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ClientResponse.java index 897a1a28b5d7..90384a6ede04 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ClientResponse.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ClientResponse.java @@ -193,9 +193,9 @@ public interface ClientResponse { String logPrefix(); /** - * Return a builder to mutate the this response, for example to change + * Return a builder to mutate this response, for example to change * the status, headers, cookies, and replace or transform the body. - * @return a builder to mutate the request with + * @return a builder to mutate the response with * @since 5.3 */ default Builder mutate() { diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RequestPredicate.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RequestPredicate.java index 57f18db299e6..0743dcec4dec 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RequestPredicate.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RequestPredicate.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -71,7 +71,7 @@ default RequestPredicate or(RequestPredicate other) { /** * Transform the given request into a request used for a nested route. For instance, - * a path-based predicate can return a {@code ServerRequest} with a the path remaining + * a path-based predicate can return a {@code ServerRequest} with a path remaining * after a match. *

        The default implementation returns an {@code Optional} wrapping the given request if * {@link #test(ServerRequest)} evaluates to {@code true}; or {@link Optional#empty()} diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/AbstractHandlerMethodMapping.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/AbstractHandlerMethodMapping.java index 93ff062651e1..c2e01aaeff70 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/AbstractHandlerMethodMapping.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/AbstractHandlerMethodMapping.java @@ -42,6 +42,7 @@ import org.springframework.util.ClassUtils; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; +import org.springframework.util.StringUtils; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.reactive.CorsUtils; import org.springframework.web.method.HandlerMethod; @@ -222,9 +223,12 @@ else if (mappingsLogger.isDebugEnabled()) { } private String formatMappings(Class userType, Map methods) { - String formattedType = Arrays.stream(ClassUtils.getPackageName(userType).split("\\.")) - .map(p -> p.substring(0, 1)) - .collect(Collectors.joining(".", "", "." + userType.getSimpleName())); + String packageName = ClassUtils.getPackageName(userType); + String formattedType = (StringUtils.hasText(packageName) ? + Arrays.stream(packageName.split("\\.")) + .map(packageSegment -> packageSegment.substring(0, 1)) + .collect(Collectors.joining(".", "", "." + userType.getSimpleName())) : + userType.getSimpleName()); Function methodFormatter = method -> Arrays.stream(method.getParameterTypes()) .map(Class::getSimpleName) .collect(Collectors.joining(",", "(", ")")); diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/InvocableHandlerMethod.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/InvocableHandlerMethod.java index fb2e31a52479..b117a197aa8e 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/InvocableHandlerMethod.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/InvocableHandlerMethod.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -37,7 +37,6 @@ import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.lang.Nullable; import org.springframework.util.ObjectUtils; -import org.springframework.util.ReflectionUtils; import org.springframework.web.method.HandlerMethod; import org.springframework.web.reactive.BindingContext; import org.springframework.web.reactive.HandlerResult; @@ -137,7 +136,6 @@ public Mono invoke( return getMethodArgumentValues(exchange, bindingContext, providedArgs).flatMap(args -> { Object value; try { - ReflectionUtils.makeAccessible(getBridgedMethod()); Method method = getBridgedMethod(); if (KotlinDetector.isSuspendingFunction(method)) { value = CoroutinesUtils.invokeSuspendingFunction(method, getBean(), args); diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/socket/HandshakeInfo.java b/spring-webflux/src/main/java/org/springframework/web/reactive/socket/HandshakeInfo.java index 657a20408c84..0bef75a832ca 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/socket/HandshakeInfo.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/socket/HandshakeInfo.java @@ -77,7 +77,7 @@ public HandshakeInfo(URI uri, HttpHeaders headers, Mono principal, @N } /** - * Constructor targeting server-side use with extra information such as the + * Constructor targeting server-side use with extra information such as * the remote address, attributes, and a log prefix. * @param uri the endpoint URL * @param headers server request headers diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilderTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilderTests.java index 47fdfdf430f8..5bff972bdd2e 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilderTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -51,30 +51,63 @@ */ public class DefaultClientRequestBuilderTests { + private static final URI DEFAULT_URL = URI.create("https://example.com"); + @Test - public void from() throws URISyntaxException { - ClientRequest other = ClientRequest.create(GET, URI.create("https://example.com")) + public void from() { + ClientRequest other = ClientRequest.create(GET, DEFAULT_URL) .header("foo", "bar") .cookie("baz", "qux") + .attribute("attributeKey", "attributeValue") + .attribute("anotherAttributeKey", "anotherAttributeValue") .httpRequest(request -> {}) .build(); + ClientRequest result = ClientRequest.from(other) .headers(httpHeaders -> httpHeaders.set("foo", "baar")) .cookies(cookies -> cookies.set("baz", "quux")) .build(); - assertThat(result.url()).isEqualTo(new URI("https://example.com")); + + assertThat(result.url()).isEqualTo(DEFAULT_URL); assertThat(result.method()).isEqualTo(GET); assertThat(result.headers().size()).isEqualTo(1); assertThat(result.headers().getFirst("foo")).isEqualTo("baar"); assertThat(result.cookies().size()).isEqualTo(1); assertThat(result.cookies().getFirst("baz")).isEqualTo("quux"); assertThat(result.httpRequest()).isNotNull(); + assertThat(result.attributes().get("attributeKey")).isEqualTo("attributeValue"); + assertThat(result.attributes().get("anotherAttributeKey")).isEqualTo("anotherAttributeValue"); + } + + @Test + public void fromCopiesBody() { + String body = "foo"; + BodyInserter inserter = (response, strategies) -> { + byte[] bodyBytes = body.getBytes(UTF_8); + DataBuffer buffer = DefaultDataBufferFactory.sharedInstance.wrap(bodyBytes); + return response.writeWith(Mono.just(buffer)); + }; + + ClientRequest other = ClientRequest.create(POST, DEFAULT_URL).body(inserter).build(); + ClientRequest result = ClientRequest.from(other).build(); + + List> messageWriters = new ArrayList<>(); + messageWriters.add(new EncoderHttpMessageWriter<>(CharSequenceEncoder.allMimeTypes())); + + ExchangeStrategies strategies = mock(ExchangeStrategies.class); + given(strategies.messageWriters()).willReturn(messageWriters); + + MockClientHttpRequest request = new MockClientHttpRequest(POST, "/"); + result.writeTo(request, strategies).block(); + + String copiedBody = request.getBodyAsString().block(); + + assertThat(copiedBody).isEqualTo("foo"); } @Test - public void method() throws URISyntaxException { - URI url = new URI("https://example.com"); - ClientRequest.Builder builder = ClientRequest.create(DELETE, url); + public void method() { + ClientRequest.Builder builder = ClientRequest.create(DELETE, DEFAULT_URL); assertThat(builder.build().method()).isEqualTo(DELETE); builder.method(OPTIONS); @@ -94,18 +127,17 @@ public void url() throws URISyntaxException { @Test public void cookie() { - ClientRequest result = ClientRequest.create(GET, URI.create("https://example.com")) - .cookie("foo", "bar").build(); + ClientRequest result = ClientRequest.create(GET, DEFAULT_URL).cookie("foo", "bar").build(); assertThat(result.cookies().getFirst("foo")).isEqualTo("bar"); } @Test public void build() { - ClientRequest result = ClientRequest.create(GET, URI.create("https://example.com")) + ClientRequest result = ClientRequest.create(GET, DEFAULT_URL) .header("MyKey", "MyValue") .cookie("foo", "bar") .httpRequest(request -> { - MockClientHttpRequest nativeRequest = (MockClientHttpRequest) request.getNativeRequest(); + MockClientHttpRequest nativeRequest = request.getNativeRequest(); nativeRequest.getHeaders().add("MyKey2", "MyValue2"); }) .build(); @@ -125,16 +157,14 @@ public void build() { @Test public void bodyInserter() { String body = "foo"; - BodyInserter inserter = - (response, strategies) -> { - byte[] bodyBytes = body.getBytes(UTF_8); - DataBuffer buffer = DefaultDataBufferFactory.sharedInstance.wrap(bodyBytes); + BodyInserter inserter = (response, strategies) -> { + byte[] bodyBytes = body.getBytes(UTF_8); + DataBuffer buffer = DefaultDataBufferFactory.sharedInstance.wrap(bodyBytes); - return response.writeWith(Mono.just(buffer)); - }; + return response.writeWith(Mono.just(buffer)); + }; - ClientRequest result = ClientRequest.create(POST, URI.create("https://example.com")) - .body(inserter).build(); + ClientRequest result = ClientRequest.create(POST, DEFAULT_URL).body(inserter).build(); List> messageWriters = new ArrayList<>(); messageWriters.add(new EncoderHttpMessageWriter<>(CharSequenceEncoder.allMimeTypes())); @@ -146,17 +176,14 @@ public void bodyInserter() { result.writeTo(request, strategies).block(); assertThat(request.getBody()).isNotNull(); - StepVerifier.create(request.getBody()) - .expectNextCount(1) - .verifyComplete(); + StepVerifier.create(request.getBody()).expectNextCount(1).verifyComplete(); } @Test public void bodyClass() { String body = "foo"; Publisher publisher = Mono.just(body); - ClientRequest result = ClientRequest.create(POST, URI.create("https://example.com")) - .body(publisher, String.class).build(); + ClientRequest result = ClientRequest.create(POST, DEFAULT_URL).body(publisher, String.class).build(); List> messageWriters = new ArrayList<>(); messageWriters.add(new EncoderHttpMessageWriter<>(CharSequenceEncoder.allMimeTypes())); @@ -168,9 +195,7 @@ public void bodyClass() { result.writeTo(request, strategies).block(); assertThat(request.getBody()).isNotNull(); - StepVerifier.create(request.getBody()) - .expectNextCount(1) - .verifyComplete(); + StepVerifier.create(request.getBody()).expectNextCount(1).verifyComplete(); } @Test @@ -178,8 +203,7 @@ public void bodyParameterizedTypeReference() { String body = "foo"; Publisher publisher = Mono.just(body); ParameterizedTypeReference typeReference = new ParameterizedTypeReference() {}; - ClientRequest result = ClientRequest.create(POST, URI.create("https://example.com")) - .body(publisher, typeReference).build(); + ClientRequest result = ClientRequest.create(POST, DEFAULT_URL).body(publisher, typeReference).build(); List> messageWriters = new ArrayList<>(); messageWriters.add(new EncoderHttpMessageWriter<>(CharSequenceEncoder.allMimeTypes())); @@ -191,9 +215,7 @@ public void bodyParameterizedTypeReference() { result.writeTo(request, strategies).block(); assertThat(request.getBody()).isNotNull(); - StepVerifier.create(request.getBody()) - .expectNextCount(1) - .verifyComplete(); + StepVerifier.create(request.getBody()).expectNextCount(1).verifyComplete(); } } diff --git a/spring-webmvc/spring-webmvc.gradle b/spring-webmvc/spring-webmvc.gradle index 92deba6aa2f6..99e70f68f622 100644 --- a/spring-webmvc/spring-webmvc.gradle +++ b/spring-webmvc/spring-webmvc.gradle @@ -3,12 +3,12 @@ description = "Spring Web MVC" apply plugin: "kotlin" dependencies { - compile(project(":spring-aop")) - compile(project(":spring-beans")) - compile(project(":spring-context")) - compile(project(":spring-core")) - compile(project(":spring-expression")) - compile(project(":spring-web")) + api(project(":spring-aop")) + api(project(":spring-beans")) + api(project(":spring-context")) + api(project(":spring-core")) + api(project(":spring-expression")) + api(project(":spring-web")) compileOnly("javax.servlet:javax.servlet-api") compileOnly("com.google.code.findbugs:findbugs") // for groovy-templates optional(project(":spring-context-support")) // for FreeMarker support @@ -37,38 +37,37 @@ dependencies { optional("org.jetbrains.kotlin:kotlin-stdlib") optional("org.reactivestreams:reactive-streams") optional("org.jetbrains.kotlinx:kotlinx-coroutines-reactor") - testCompile(project(":kotlin-coroutines")) - testCompile(testFixtures(project(":spring-beans"))) - testCompile(testFixtures(project(":spring-core"))) - testCompile(testFixtures(project(":spring-context"))) - testCompile(testFixtures(project(":spring-web"))) - testCompile("javax.servlet:javax.servlet-api") - testCompile("org.eclipse.jetty:jetty-servlet") { + testImplementation(testFixtures(project(":spring-beans"))) + testImplementation(testFixtures(project(":spring-core"))) + testImplementation(testFixtures(project(":spring-context"))) + testImplementation(testFixtures(project(":spring-web"))) + testImplementation("javax.servlet:javax.servlet-api") + testImplementation("org.eclipse.jetty:jetty-servlet") { exclude group: "javax.servlet", module: "javax.servlet" } - testCompile("org.eclipse.jetty:jetty-server") { + testImplementation("org.eclipse.jetty:jetty-server") { exclude group: "javax.servlet", module: "javax.servlet" } - testCompile("org.apache.httpcomponents:httpclient") - testCompile("commons-fileupload:commons-fileupload") - testCompile("commons-io:commons-io") - testCompile("joda-time:joda-time") - testCompile("org.mozilla:rhino") - testCompile("org.dom4j:dom4j") - testCompile("jaxen:jaxen") - testCompile("org.xmlunit:xmlunit-assertj") - testCompile("org.xmlunit:xmlunit-matchers") - testCompile("org.hibernate:hibernate-validator") - testCompile("javax.validation:validation-api") - testCompile("io.projectreactor:reactor-core") - testCompile("io.reactivex.rxjava3:rxjava") - testCompile("org.jetbrains.kotlin:kotlin-script-runtime") - testRuntime("org.jetbrains.kotlin:kotlin-scripting-jsr223") - testRuntime("org.jruby:jruby") - testRuntime("org.python:jython-standalone") - testRuntime("org.webjars:underscorejs") - testRuntime("org.glassfish:javax.el") - testRuntime("com.sun.xml.bind:jaxb-core") - testRuntime("com.sun.xml.bind:jaxb-impl") - testRuntime("com.sun.activation:javax.activation") + testImplementation("org.apache.httpcomponents:httpclient") + testImplementation("commons-fileupload:commons-fileupload") + testImplementation("commons-io:commons-io") + testImplementation("joda-time:joda-time") + testImplementation("org.mozilla:rhino") + testImplementation("org.dom4j:dom4j") + testImplementation("jaxen:jaxen") + testImplementation("org.xmlunit:xmlunit-assertj") + testImplementation("org.xmlunit:xmlunit-matchers") + testImplementation("org.hibernate:hibernate-validator") + testImplementation("javax.validation:validation-api") + testImplementation("io.projectreactor:reactor-core") + testImplementation("io.reactivex.rxjava3:rxjava") + testImplementation("org.jetbrains.kotlin:kotlin-script-runtime") + testRuntimeOnly("org.jetbrains.kotlin:kotlin-scripting-jsr223") + testRuntimeOnly("org.jruby:jruby") + testRuntimeOnly("org.python:jython-standalone") + testRuntimeOnly("org.webjars:underscorejs") + testRuntimeOnly("org.glassfish:javax.el") + testRuntimeOnly("com.sun.xml.bind:jaxb-core") + testRuntimeOnly("com.sun.xml.bind:jaxb-impl") + testRuntimeOnly("com.sun.activation:javax.activation") } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java index 19cb32564ce7..5be28f3e13e0 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java @@ -978,7 +978,10 @@ protected void doService(HttpServletRequest request, HttpServletResponse respons private void logRequest(HttpServletRequest request) { LogFormatUtils.traceDebug(logger, traceOn -> { String params; - if (isEnableLoggingRequestDetails()) { + if (StringUtils.startsWithIgnoreCase(request.getContentType(), "multipart/")) { + params = "multipart"; + } + else if (isEnableLoggingRequestDetails()) { params = request.getParameterMap().entrySet().stream() .map(entry -> entry.getKey() + ":" + Arrays.toString(entry.getValue())) .collect(Collectors.joining(", ")); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/FrameworkServlet.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/FrameworkServlet.java index 6d3e8d3d2b45..40e1d1030e91 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/FrameworkServlet.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/FrameworkServlet.java @@ -1085,7 +1085,7 @@ private void logResult(HttpServletRequest request, HttpServletResponse response, } DispatcherType dispatchType = request.getDispatcherType(); - boolean initialDispatch = DispatcherType.REQUEST == dispatchType; + boolean initialDispatch = (dispatchType == DispatcherType.REQUEST); if (failureCause != null) { if (!initialDispatch) { @@ -1109,7 +1109,7 @@ else if (logger.isTraceEnabled()) { } int status = response.getStatus(); - String headers = ""; // nothing below trace + String headers = ""; // nothing below trace if (logger.isTraceEnabled()) { Collection names = response.getHeaderNames(); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/RequestPredicate.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/RequestPredicate.java index 4e9ec82d5b71..3c1ac3474c14 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/RequestPredicate.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/RequestPredicate.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -71,7 +71,7 @@ default RequestPredicate or(RequestPredicate other) { /** * Transform the given request into a request used for a nested route. For instance, - * a path-based predicate can return a {@code ServerRequest} with a the path remaining + * a path-based predicate can return a {@code ServerRequest} with a path remaining * after a match. *

        The default implementation returns an {@code Optional} wrapping the given request if * {@link #test(ServerRequest)} evaluates to {@code true}; or {@link Optional#empty()} diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java index 900b7881be90..d3336710f0c4 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java @@ -276,7 +276,7 @@ public void setInterceptors(Object... interceptors) { * determines the {@code CorsConfiguration} to use which is then further * {@link CorsConfiguration#combine(CorsConfiguration) combined} with the * {@code CorsConfiguration} for the selected handler. - *

        This is mutually exclusie with + *

        This is mutually exclusive with * {@link #setCorsConfigurationSource(CorsConfigurationSource)}. * @since 4.2 * @see #setCorsProcessor(CorsProcessor) @@ -305,7 +305,7 @@ public void setCorsConfigurations(Map corsConfigurati * {@code CorsConfiguration} determined by the source is * {@link CorsConfiguration#combine(CorsConfiguration) combined} with the * {@code CorsConfiguration} for the selected handler. - *

        This is mutually exclusie with {@link #setCorsConfigurations(Map)}. + *

        This is mutually exclusive with {@link #setCorsConfigurations(Map)}. * @since 5.1 * @see #setCorsProcessor(CorsProcessor) */ diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java index 367ca74997da..46f1707d1cfb 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java @@ -44,6 +44,7 @@ import org.springframework.util.ClassUtils; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; +import org.springframework.util.StringUtils; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsUtils; import org.springframework.web.method.HandlerMethod; @@ -301,9 +302,12 @@ else if (mappingsLogger.isDebugEnabled()) { } private String formatMappings(Class userType, Map methods) { - String formattedType = Arrays.stream(ClassUtils.getPackageName(userType).split("\\.")) - .map(p -> p.substring(0, 1)) - .collect(Collectors.joining(".", "", "." + userType.getSimpleName())); + String packageName = ClassUtils.getPackageName(userType); + String formattedType = (StringUtils.hasText(packageName) ? + Arrays.stream(packageName.split("\\.")) + .map(packageSegment -> packageSegment.substring(0, 1)) + .collect(Collectors.joining(".", "", "." + userType.getSimpleName())) : + userType.getSimpleName()); Function methodFormatter = method -> Arrays.stream(method.getParameterTypes()) .map(Class::getSimpleName) .collect(Collectors.joining(",", "(", ")")); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/PatternsRequestCondition.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/PatternsRequestCondition.java index d04b26942f4c..9539415ae388 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/PatternsRequestCondition.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/PatternsRequestCondition.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -87,7 +87,7 @@ public PatternsRequestCondition(String[] patterns, boolean useTrailingSlashMatc * Variant of {@link #PatternsRequestCondition(String...)} with a * {@link UrlPathHelper} and a {@link PathMatcher}, and whether to match * trailing slashes. - *

        As of 5.3 the the path is obtained through the static method + *

        As of 5.3 the path is obtained through the static method * {@link UrlPathHelper#getResolvedLookupPath} and a {@code UrlPathHelper} * does not need to be passed in. * @since 5.2.4 @@ -105,7 +105,7 @@ public PatternsRequestCondition(String[] patterns, @Nullable UrlPathHelper urlPa * Variant of {@link #PatternsRequestCondition(String...)} with a * {@link UrlPathHelper} and a {@link PathMatcher}, and flags for matching * with suffixes and trailing slashes. - *

        As of 5.3 the the path is obtained through the static method + *

        As of 5.3 the path is obtained through the static method * {@link UrlPathHelper#getResolvedLookupPath} and a {@code UrlPathHelper} * does not need to be passed in. * @deprecated as of 5.2.4. See class-level note in @@ -123,7 +123,7 @@ public PatternsRequestCondition(String[] patterns, @Nullable UrlPathHelper urlPa * Variant of {@link #PatternsRequestCondition(String...)} with a * {@link UrlPathHelper} and a {@link PathMatcher}, and flags for matching * with suffixes and trailing slashes, along with specific extensions. - *

        As of 5.3 the the path is obtained through the static method + *

        As of 5.3 the path is obtained through the static method * {@link UrlPathHelper#getResolvedLookupPath} and a {@code UrlPathHelper} * does not need to be passed in. * @deprecated as of 5.2.4. See class-level note in diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/RequestMappingInfo.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/RequestMappingInfo.java index a0dadcd798a1..79622c386169 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/RequestMappingInfo.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/RequestMappingInfo.java @@ -47,7 +47,7 @@ import org.springframework.web.util.pattern.PathPatternParser; /** - * Request mapping information. A composite for the the following conditions: + * Request mapping information. A composite for the following conditions: *

          *
        1. {@link PathPatternsRequestCondition} with parsed {@code PathPatterns} or * {@link PatternsRequestCondition} with String patterns via {@code PathMatcher} diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java index bdb29fc15a2b..7be174e7a68b 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java @@ -483,7 +483,7 @@ protected ServletInvocableHandlerMethod getExceptionHandlerMethod( } Method method = resolver.resolveMethod(exception); if (method != null) { - return new ServletInvocableHandlerMethod(handlerMethod.getBean(), method); + return new ServletInvocableHandlerMethod(handlerMethod.getBean(), method, this.applicationContext); } // For advice applicability check below (involving base packages, assignable types // and annotation presence), use target class instead of interface-based proxy. @@ -498,7 +498,7 @@ protected ServletInvocableHandlerMethod getExceptionHandlerMethod( ExceptionHandlerMethodResolver resolver = entry.getValue(); Method method = resolver.resolveMethod(exception); if (method != null) { - return new ServletInvocableHandlerMethod(advice.resolveBean(), method); + return new ServletInvocableHandlerMethod(advice.resolveBean(), method, this.applicationContext); } } } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java index 8cbdb10549db..ae3473873dee 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -25,6 +25,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.springframework.context.MessageSource; import org.springframework.core.KotlinDetector; import org.springframework.core.MethodParameter; import org.springframework.core.ResolvableType; @@ -76,6 +77,16 @@ public ServletInvocableHandlerMethod(Object handler, Method method) { super(handler, method); } + /** + * Variant of {@link #ServletInvocableHandlerMethod(Object, Method)} that + * also accepts a {@link MessageSource}, e.g. to resolve + * {@code @ResponseStatus} messages with. + * @since 5.3.10 + */ + public ServletInvocableHandlerMethod(Object handler, Method method, @Nullable MessageSource messageSource) { + super(handler, method, messageSource); + } + /** * Create an instance from a {@code HandlerMethod}. */ @@ -184,7 +195,7 @@ private String formatErrorForReturnValue(@Nullable Object returnValue) { /** * Create a nested ServletInvocableHandlerMethod subclass that returns the - * the given value (or raises an Exception if the value is one) rather than + * given value (or raises an Exception if the value is one) rather than * actually invoking the controller method. This is useful when processing * async return values (e.g. Callable, DeferredResult, ListenableFuture). */ diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/PathPatternsParameterizedTest.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/PathPatternsParameterizedTest.java index 7dc77ff73d18..ead6e38ab1da 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/PathPatternsParameterizedTest.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/PathPatternsParameterizedTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.web.servlet.handler; import java.lang.annotation.ElementType; @@ -30,7 +31,9 @@ */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) -@org.junit.jupiter.params.ParameterizedTest +// Do not auto-close arguments since ConfigurableWebApplicationContext implements +// AutoCloseable and is shared between parameterized test invocations. +@org.junit.jupiter.params.ParameterizedTest(autoCloseArguments = false) @org.junit.jupiter.params.provider.MethodSource("pathPatternsArguments") public @interface PathPatternsParameterizedTest { } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/CrossOriginTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/CrossOriginTests.java index 3f1fce6612a2..f4fa67d7ce8a 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/CrossOriginTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/CrossOriginTests.java @@ -159,7 +159,7 @@ void defaultAnnotation(TestRequestMappingInfoHandlerMapping mapping) throws Exce assertThat(config.getAllowCredentials()).isNull(); assertThat(config.getAllowedHeaders()).containsExactly("*"); assertThat(CollectionUtils.isEmpty(config.getExposedHeaders())).isTrue(); - assertThat(config.getMaxAge()).isEqualTo(new Long(1800)); + assertThat(config.getMaxAge()).isEqualTo(Long.valueOf(1800)); } @PathPatternsParameterizedTest @@ -173,7 +173,7 @@ void customized(TestRequestMappingInfoHandlerMapping mapping) throws Exception { assertThat(config.getAllowedOrigins()).containsExactly("https://site1.com", "https://site2.com"); assertThat(config.getAllowedHeaders()).containsExactly("header1", "header2"); assertThat(config.getExposedHeaders()).containsExactly("header3", "header4"); - assertThat(config.getMaxAge()).isEqualTo(new Long(123)); + assertThat(config.getMaxAge()).isEqualTo(Long.valueOf(123)); assertThat(config.getAllowCredentials()).isFalse(); } @@ -315,7 +315,7 @@ void preFlightRequest(TestRequestMappingInfoHandlerMapping mapping) throws Excep assertThat(config.getAllowCredentials()).isNull(); assertThat(config.getAllowedHeaders()).containsExactly("*"); assertThat(CollectionUtils.isEmpty(config.getExposedHeaders())).isTrue(); - assertThat(config.getMaxAge()).isEqualTo(new Long(1800)); + assertThat(config.getMaxAge()).isEqualTo(Long.valueOf(1800)); } @PathPatternsParameterizedTest @@ -389,7 +389,7 @@ private CorsConfiguration getCorsConfiguration(@Nullable HandlerExecutionChain c assertThat(chain).isNotNull(); if (isPreFlightRequest) { Object handler = chain.getHandler(); - assertThat(handler.getClass().getSimpleName().equals("PreFlightHandler")).isTrue(); + assertThat(handler.getClass().getSimpleName()).isEqualTo("PreFlightHandler"); DirectFieldAccessor accessor = new DirectFieldAccessor(handler); return (CorsConfiguration)accessor.getPropertyValue("config"); } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolverTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolverTests.java index b3757c556eb4..960935036266 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolverTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolverTests.java @@ -19,7 +19,9 @@ import java.io.IOException; import java.io.UnsupportedEncodingException; import java.io.Writer; +import java.net.SocketTimeoutException; import java.util.Collections; +import java.util.Locale; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -30,8 +32,11 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.context.support.StaticApplicationContext; import org.springframework.core.MethodParameter; import org.springframework.core.annotation.Order; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.server.ServerHttpRequest; @@ -42,6 +47,7 @@ import org.springframework.web.HttpRequestHandler; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.context.support.WebApplicationObjectSupport; import org.springframework.web.method.HandlerMethod; @@ -333,6 +339,28 @@ void resolveExceptionWithAssertionErrorAsRootCause() throws Exception { assertThat(this.response.getContentAsString()).isEqualTo(rootCause.toString()); } + @Test //gh-27156 + void resolveExceptionWithReasonResovledByMessageSource() throws Exception { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MyConfig.class); + StaticApplicationContext context = new StaticApplicationContext(ctx); + Locale locale = Locale.ENGLISH; + context.addMessage("gateway.timeout", locale, "Gateway Timeout"); + context.refresh(); + LocaleContextHolder.setLocale(locale); + this.resolver.setApplicationContext(context); + this.resolver.afterPropertiesSet(); + + SocketTimeoutException ex = new SocketTimeoutException(); + HandlerMethod handlerMethod = new HandlerMethod(new ResponseBodyController(), "handle"); + ModelAndView mav = this.resolver.resolveException(this.request, this.response, handlerMethod, ex); + + assertThat(mav).as("Exception was not handled").isNotNull(); + assertThat(mav.isEmpty()).isTrue(); + assertThat(this.response.getStatus()).isEqualTo(HttpStatus.GATEWAY_TIMEOUT.value()); + assertThat(this.response.getErrorMessage()).isEqualTo("Gateway Timeout"); + assertThat(this.response.getContentAsString()).isEqualTo(""); + } + @Test void resolveExceptionControllerAdviceHandler() throws Exception { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MyControllerAdviceConfig.class); @@ -530,6 +558,16 @@ public String handleException(Exception ex) { } } + @RestControllerAdvice + @Order(3) + static class ResponseStatusTestExceptionResolver { + + @ExceptionHandler(SocketTimeoutException.class) + @ResponseStatus(code = HttpStatus.GATEWAY_TIMEOUT, reason = "gateway.timeout") + public void handleException(SocketTimeoutException ex) { + + } + } @Configuration static class MyConfig { @@ -543,6 +581,11 @@ public TestExceptionResolver testExceptionResolver() { public AnotherTestExceptionResolver anotherTestExceptionResolver() { return new AnotherTestExceptionResolver(); } + + @Bean + public ResponseStatusTestExceptionResolver responseStatusTestExceptionResolver() { + return new ResponseStatusTestExceptionResolver(); + } } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/support/RedirectAttributesModelMapTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/support/RedirectAttributesModelMapTests.java index 9e8da5248e67..41ee86b09401 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/support/RedirectAttributesModelMapTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/support/RedirectAttributesModelMapTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -38,7 +38,7 @@ * @author Rossen Stoyanchev * @since 3.1 */ -public class RedirectAttributesModelMapTests { +class RedirectAttributesModelMapTests { private RedirectAttributesModelMap redirectAttributes; @@ -54,13 +54,13 @@ public void setup() { } @Test - public void addAttributePrimitiveType() { + void addAttributePrimitiveType() { this.redirectAttributes.addAttribute("speed", 65); assertThat(this.redirectAttributes.get("speed")).isEqualTo("65"); } @Test - public void addAttributeCustomType() { + void addAttributeCustomType() { String attrName = "person"; this.redirectAttributes.addAttribute(attrName, new TestBean("Fred")); @@ -73,7 +73,7 @@ public void addAttributeCustomType() { } @Test - public void addAttributeToString() { + void addAttributeToString() { String attrName = "person"; RedirectAttributesModelMap model = new RedirectAttributesModelMap(); model.addAttribute(attrName, new TestBean("Fred")); @@ -82,22 +82,22 @@ public void addAttributeToString() { } @Test - public void addAttributeValue() { + void addAttributeValue() { this.redirectAttributes.addAttribute(new TestBean("Fred")); assertThat(this.redirectAttributes.get("testBean")).isEqualTo("Fred"); } @Test - public void addAllAttributesList() { - this.redirectAttributes.addAllAttributes(Arrays.asList(new TestBean("Fred"), new Integer(5))); + void addAllAttributesList() { + this.redirectAttributes.addAllAttributes(Arrays.asList(new TestBean("Fred"), 5)); assertThat(this.redirectAttributes.get("testBean")).isEqualTo("Fred"); assertThat(this.redirectAttributes.get("integer")).isEqualTo("5"); } @Test - public void addAttributesMap() { + void addAttributesMap() { Map map = new HashMap<>(); map.put("person", new TestBean("Fred")); map.put("age", 33); @@ -108,7 +108,7 @@ public void addAttributesMap() { } @Test - public void mergeAttributes() { + void mergeAttributes() { Map map = new HashMap<>(); map.put("person", new TestBean("Fred")); map.put("age", 33); @@ -121,14 +121,14 @@ public void mergeAttributes() { } @Test - public void put() { + void put() { this.redirectAttributes.put("testBean", new TestBean("Fred")); assertThat(this.redirectAttributes.get("testBean")).isEqualTo("Fred"); } @Test - public void putAll() { + void putAll() { Map map = new HashMap<>(); map.put("person", new TestBean("Fred")); map.put("age", 33); diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/BindTagTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/BindTagTests.java index d8f92d4de72e..24a9942e3499 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/BindTagTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/BindTagTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -50,10 +50,10 @@ * @author Alef Arendsen * @author Mark Fisher */ -public class BindTagTests extends AbstractTagTests { +class BindTagTests extends AbstractTagTests { @Test - public void bindTagWithoutErrors() throws JspException { + void bindTagWithoutErrors() throws JspException { PageContext pc = createPageContext(); Errors errors = new ServletRequestDataBinder(new TestBean(), "tb").getBindingResult(); pc.getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + "tb", errors); @@ -76,7 +76,7 @@ public void bindTagWithoutErrors() throws JspException { } @Test - public void bindTagWithGlobalErrors() throws JspException { + void bindTagWithGlobalErrors() throws JspException { PageContext pc = createPageContext(); Errors errors = new ServletRequestDataBinder(new TestBean(), "tb").getBindingResult(); errors.reject("code1", "message1"); @@ -116,7 +116,7 @@ public void bindTagWithGlobalErrors() throws JspException { } @Test - public void bindTagWithGlobalErrorsAndNoDefaultMessage() throws JspException { + void bindTagWithGlobalErrorsAndNoDefaultMessage() throws JspException { PageContext pc = createPageContext(); Errors errors = new ServletRequestDataBinder(new TestBean(), "tb").getBindingResult(); errors.reject("code1"); @@ -150,7 +150,7 @@ public void bindTagWithGlobalErrorsAndNoDefaultMessage() throws JspException { } @Test - public void bindTagWithGlobalErrorsAndDefaultMessageOnly() throws JspException { + void bindTagWithGlobalErrorsAndDefaultMessageOnly() throws JspException { PageContext pc = createPageContext(); Errors errors = new ServletRequestDataBinder(new TestBean(), "tb").getBindingResult(); errors.reject(null, "message1"); @@ -186,7 +186,7 @@ public void bindTagWithGlobalErrorsAndDefaultMessageOnly() throws JspException { } @Test - public void bindStatusGetErrorMessagesAsString() throws JspException { + void bindStatusGetErrorMessagesAsString() throws JspException { // one error (should not include delimiter) PageContext pc = createPageContext(); Errors errors = new ServletRequestDataBinder(new TestBean(), "tb").getBindingResult(); @@ -225,7 +225,7 @@ public void bindStatusGetErrorMessagesAsString() throws JspException { } @Test - public void bindTagWithFieldErrors() throws JspException { + void bindTagWithFieldErrors() throws JspException { PageContext pc = createPageContext(); TestBean tb = new TestBean(); tb.setName("name1"); @@ -263,7 +263,7 @@ public void bindTagWithFieldErrors() throws JspException { status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE); assertThat(status != null).as("Has status variable").isTrue(); assertThat("age".equals(status.getExpression())).as("Correct expression").isTrue(); - assertThat(new Integer(0).equals(status.getValue())).as("Correct value").isTrue(); + assertThat(Integer.valueOf(0).equals(status.getValue())).as("Correct value").isTrue(); assertThat("0".equals(status.getDisplayValue())).as("Correct displayValue").isTrue(); assertThat(status.isError()).as("Correct isError").isTrue(); assertThat(status.getErrorCodes().length == 1).as("Correct errorCodes").isTrue(); @@ -295,7 +295,7 @@ public void bindTagWithFieldErrors() throws JspException { } @Test - public void bindTagWithFieldErrorsAndNoDefaultMessage() throws JspException { + void bindTagWithFieldErrorsAndNoDefaultMessage() throws JspException { PageContext pc = createPageContext(); TestBean tb = new TestBean(); tb.setName("name1"); @@ -328,7 +328,7 @@ public void bindTagWithFieldErrorsAndNoDefaultMessage() throws JspException { status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE); assertThat(status != null).as("Has status variable").isTrue(); assertThat("age".equals(status.getExpression())).as("Correct expression").isTrue(); - assertThat(new Integer(0).equals(status.getValue())).as("Correct value").isTrue(); + assertThat(Integer.valueOf(0).equals(status.getValue())).as("Correct value").isTrue(); assertThat("0".equals(status.getDisplayValue())).as("Correct displayValue").isTrue(); assertThat(status.isError()).as("Correct isError").isTrue(); assertThat(status.getErrorCodes().length == 1).as("Correct errorCodes").isTrue(); @@ -352,7 +352,7 @@ public void bindTagWithFieldErrorsAndNoDefaultMessage() throws JspException { } @Test - public void bindTagWithFieldErrorsAndDefaultMessageOnly() throws JspException { + void bindTagWithFieldErrorsAndDefaultMessageOnly() throws JspException { PageContext pc = createPageContext(); TestBean tb = new TestBean(); tb.setName("name1"); @@ -386,7 +386,7 @@ public void bindTagWithFieldErrorsAndDefaultMessageOnly() throws JspException { status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE); assertThat(status != null).as("Has status variable").isTrue(); assertThat("age".equals(status.getExpression())).as("Correct expression").isTrue(); - assertThat(new Integer(0).equals(status.getValue())).as("Correct value").isTrue(); + assertThat(Integer.valueOf(0).equals(status.getValue())).as("Correct value").isTrue(); assertThat("0".equals(status.getDisplayValue())).as("Correct displayValue").isTrue(); assertThat(status.isError()).as("Correct isError").isTrue(); assertThat(status.getErrorMessages().length == 1).as("Correct errorMessages").isTrue(); @@ -411,7 +411,7 @@ public void bindTagWithFieldErrorsAndDefaultMessageOnly() throws JspException { } @Test - public void bindTagWithNestedFieldErrors() throws JspException { + void bindTagWithNestedFieldErrors() throws JspException { PageContext pc = createPageContext(); TestBean tb = new TestBean(); tb.setName("name1"); @@ -439,7 +439,7 @@ public void bindTagWithNestedFieldErrors() throws JspException { } @Test - public void propertyExposing() throws JspException { + void propertyExposing() throws JspException { PageContext pc = createPageContext(); TestBean tb = new TestBean(); tb.setName("name1"); @@ -464,7 +464,7 @@ public void propertyExposing() throws JspException { } @Test - public void bindTagWithIndexedProperties() throws JspException { + void bindTagWithIndexedProperties() throws JspException { PageContext pc = createPageContext(); IndexedTestBean tb = new IndexedTestBean(); Errors errors = new ServletRequestDataBinder(tb, "tb").getBindingResult(); @@ -492,7 +492,7 @@ public void bindTagWithIndexedProperties() throws JspException { } @Test - public void bindTagWithMappedProperties() throws JspException { + void bindTagWithMappedProperties() throws JspException { PageContext pc = createPageContext(); IndexedTestBean tb = new IndexedTestBean(); Errors errors = new ServletRequestDataBinder(tb, "tb").getBindingResult(); @@ -520,7 +520,7 @@ public void bindTagWithMappedProperties() throws JspException { } @Test - public void bindTagWithIndexedPropertiesAndCustomEditor() throws JspException { + void bindTagWithIndexedPropertiesAndCustomEditor() throws JspException { PageContext pc = createPageContext(); IndexedTestBean tb = new IndexedTestBean(); DataBinder binder = new ServletRequestDataBinder(tb, "tb"); @@ -549,7 +549,7 @@ public String getAsText() { } @Test - public void bindTagWithToStringAndHtmlEscaping() throws JspException { + void bindTagWithToStringAndHtmlEscaping() throws JspException { PageContext pc = createPageContext(); BindTag tag = new BindTag(); tag.setPageContext(pc); @@ -568,7 +568,7 @@ public void bindTagWithToStringAndHtmlEscaping() throws JspException { } @Test - public void bindTagWithSetValueAndHtmlEscaping() throws JspException { + void bindTagWithSetValueAndHtmlEscaping() throws JspException { PageContext pc = createPageContext(); BindTag tag = new BindTag(); tag.setPageContext(pc); @@ -583,7 +583,7 @@ public void bindTagWithSetValueAndHtmlEscaping() throws JspException { } @Test - public void bindTagWithFieldButWithoutErrorsInstance() throws JspException { + void bindTagWithFieldButWithoutErrorsInstance() throws JspException { PageContext pc = createPageContext(); BindTag tag = new BindTag(); tag.setPageContext(pc); @@ -596,7 +596,7 @@ public void bindTagWithFieldButWithoutErrorsInstance() throws JspException { } @Test - public void bindTagWithFieldButWithoutErrorsInstanceAndHtmlEscaping() throws JspException { + void bindTagWithFieldButWithoutErrorsInstanceAndHtmlEscaping() throws JspException { PageContext pc = createPageContext(); BindTag tag = new BindTag(); tag.setPageContext(pc); @@ -610,7 +610,7 @@ public void bindTagWithFieldButWithoutErrorsInstanceAndHtmlEscaping() throws Jsp } @Test - public void bindTagWithBeanButWithoutErrorsInstance() throws JspException { + void bindTagWithBeanButWithoutErrorsInstance() throws JspException { PageContext pc = createPageContext(); BindTag tag = new BindTag(); tag.setPageContext(pc); @@ -623,7 +623,7 @@ public void bindTagWithBeanButWithoutErrorsInstance() throws JspException { } @Test - public void bindTagWithoutBean() throws JspException { + void bindTagWithoutBean() throws JspException { PageContext pc = createPageContext(); BindTag tag = new BindTag(); tag.setPageContext(pc); @@ -634,7 +634,7 @@ public void bindTagWithoutBean() throws JspException { @Test - public void bindErrorsTagWithoutErrors() throws JspException { + void bindErrorsTagWithoutErrors() throws JspException { PageContext pc = createPageContext(); Errors errors = new ServletRequestDataBinder(new TestBean(), "tb").getBindingResult(); pc.getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + "tb", errors); @@ -646,7 +646,7 @@ public void bindErrorsTagWithoutErrors() throws JspException { } @Test - public void bindErrorsTagWithErrors() throws JspException { + void bindErrorsTagWithErrors() throws JspException { PageContext pc = createPageContext(); Errors errors = new ServletRequestDataBinder(new TestBean(), "tb").getBindingResult(); errors.reject("test", null, "test"); @@ -659,7 +659,7 @@ public void bindErrorsTagWithErrors() throws JspException { } @Test - public void bindErrorsTagWithoutBean() throws JspException { + void bindErrorsTagWithoutBean() throws JspException { PageContext pc = createPageContext(); BindErrorsTag tag = new BindErrorsTag(); tag.setPageContext(pc); @@ -669,7 +669,7 @@ public void bindErrorsTagWithoutBean() throws JspException { @Test - public void nestedPathDoEndTag() throws JspException { + void nestedPathDoEndTag() throws JspException { PageContext pc = createPageContext(); NestedPathTag tag = new NestedPathTag(); tag.setPath("foo"); @@ -681,7 +681,7 @@ public void nestedPathDoEndTag() throws JspException { } @Test - public void nestedPathDoEndTagWithNesting() throws JspException { + void nestedPathDoEndTagWithNesting() throws JspException { PageContext pc = createPageContext(); NestedPathTag tag = new NestedPathTag(); tag.setPath("foo"); @@ -701,7 +701,7 @@ public void nestedPathDoEndTagWithNesting() throws JspException { } @Test - public void nestedPathDoStartTagInternal() throws JspException { + void nestedPathDoStartTagInternal() throws JspException { PageContext pc = createPageContext(); NestedPathTag tag = new NestedPathTag(); tag.setPath("foo"); @@ -713,7 +713,7 @@ public void nestedPathDoStartTagInternal() throws JspException { } @Test - public void nestedPathDoStartTagInternalWithNesting() throws JspException { + void nestedPathDoStartTagInternalWithNesting() throws JspException { PageContext pc = createPageContext(); NestedPathTag tag = new NestedPathTag(); tag.setPath("foo"); @@ -746,7 +746,7 @@ public void nestedPathDoStartTagInternalWithNesting() throws JspException { } @Test - public void nestedPathWithBindTag() throws JspException { + void nestedPathWithBindTag() throws JspException { PageContext pc = createPageContext(); Errors errors = new ServletRequestDataBinder(new TestBean(), "tb").getBindingResult(); pc.getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + "tb", errors); @@ -788,7 +788,7 @@ public void nestedPathWithBindTag() throws JspException { } @Test - public void nestedPathWithBindTagWithIgnoreNestedPath() throws JspException { + void nestedPathWithBindTagWithIgnoreNestedPath() throws JspException { PageContext pc = createPageContext(); Errors errors = new ServletRequestDataBinder(new TestBean(), "tb2").getBindingResult(); pc.getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + "tb2", errors); @@ -810,7 +810,7 @@ public void nestedPathWithBindTagWithIgnoreNestedPath() throws JspException { } @Test - public void transformTagCorrectBehavior() throws JspException { + void transformTagCorrectBehavior() throws JspException { // first set up the pagecontext and the bean PageContext pc = createPageContext(); TestBean tb = new TestBean(); @@ -855,7 +855,7 @@ public void transformTagCorrectBehavior() throws JspException { } @Test - public void transformTagWithHtmlEscape() throws JspException { + void transformTagWithHtmlEscape() throws JspException { // first set up the PageContext and the bean PageContext pc = createPageContext(); TestBean tb = new TestBean(); @@ -884,7 +884,7 @@ public void transformTagWithHtmlEscape() throws JspException { } @Test - public void transformTagOutsideBindTag() throws JspException { + void transformTagOutsideBindTag() throws JspException { // first set up the pagecontext and the bean PageContext pc = createPageContext(); TestBean tb = new TestBean(); @@ -915,7 +915,7 @@ public void transformTagOutsideBindTag() throws JspException { } @Test - public void transformTagNonExistingValue() throws JspException { + void transformTagNonExistingValue() throws JspException { // first set up the pagecontext and the bean PageContext pc = createPageContext(); TestBean tb = new TestBean(); @@ -942,7 +942,7 @@ public void transformTagNonExistingValue() throws JspException { } @Test - public void transformTagWithSettingOfScope() throws JspException { + void transformTagWithSettingOfScope() throws JspException { // first set up the pagecontext and the bean PageContext pc = createPageContext(); TestBean tb = new TestBean(); @@ -997,7 +997,7 @@ public void transformTagWithSettingOfScope() throws JspException { */ @SuppressWarnings("serial") @Test - public void nestingInFormTag() throws JspException { + void nestingInFormTag() throws JspException { PageContext pc = createPageContext(); TestBean tb = new TestBean(); DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/form/CheckboxTagTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/form/CheckboxTagTests.java index 164a41582682..39e1bb710b9a 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/form/CheckboxTagTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/form/CheckboxTagTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -49,7 +49,7 @@ * @author Jeremy Grelle */ @SuppressWarnings({ "rawtypes", "unchecked" }) -public class CheckboxTagTests extends AbstractFormTagTests { +class CheckboxTagTests extends AbstractFormTagTests { private CheckboxTag tag; @@ -68,7 +68,7 @@ protected TagWriter createTagWriter() { } @Test - public void withSingleValueBooleanObjectChecked() throws Exception { + void withSingleValueBooleanObjectChecked() throws Exception { this.tag.setPath("someBoolean"); int result = this.tag.doStartTag(); assertThat(result).isEqualTo(Tag.SKIP_BODY); @@ -91,7 +91,7 @@ public void withSingleValueBooleanObjectChecked() throws Exception { } @Test - public void withIndexedBooleanObjectNotChecked() throws Exception { + void withIndexedBooleanObjectNotChecked() throws Exception { this.tag.setPath("someMap[key]"); int result = this.tag.doStartTag(); assertThat(result).isEqualTo(Tag.SKIP_BODY); @@ -114,7 +114,7 @@ public void withIndexedBooleanObjectNotChecked() throws Exception { } @Test - public void withSingleValueBooleanObjectCheckedAndDynamicAttributes() throws Exception { + void withSingleValueBooleanObjectCheckedAndDynamicAttributes() throws Exception { String dynamicAttribute1 = "attr1"; String dynamicAttribute2 = "attr2"; @@ -144,7 +144,7 @@ public void withSingleValueBooleanObjectCheckedAndDynamicAttributes() throws Exc } @Test - public void withSingleValueBooleanChecked() throws Exception { + void withSingleValueBooleanChecked() throws Exception { this.tag.setPath("jedi"); int result = this.tag.doStartTag(); assertThat(result).isEqualTo(Tag.SKIP_BODY); @@ -164,7 +164,7 @@ public void withSingleValueBooleanChecked() throws Exception { } @Test - public void withSingleValueBooleanObjectUnchecked() throws Exception { + void withSingleValueBooleanObjectUnchecked() throws Exception { this.bean.setSomeBoolean(Boolean.FALSE); this.tag.setPath("someBoolean"); int result = this.tag.doStartTag(); @@ -186,7 +186,7 @@ public void withSingleValueBooleanObjectUnchecked() throws Exception { } @Test - public void withSingleValueBooleanUnchecked() throws Exception { + void withSingleValueBooleanUnchecked() throws Exception { this.bean.setJedi(false); this.tag.setPath("jedi"); int result = this.tag.doStartTag(); @@ -208,7 +208,7 @@ public void withSingleValueBooleanUnchecked() throws Exception { } @Test - public void withSingleValueNull() throws Exception { + void withSingleValueNull() throws Exception { this.bean.setName(null); this.tag.setPath("name"); this.tag.setValue("Rob Harrop"); @@ -231,7 +231,7 @@ public void withSingleValueNull() throws Exception { } @Test - public void withSingleValueNotNull() throws Exception { + void withSingleValueNotNull() throws Exception { this.bean.setName("Rob Harrop"); this.tag.setPath("name"); this.tag.setValue("Rob Harrop"); @@ -254,7 +254,7 @@ public void withSingleValueNotNull() throws Exception { } @Test - public void withSingleValueAndEditor() throws Exception { + void withSingleValueAndEditor() throws Exception { this.bean.setName("Rob Harrop"); this.tag.setPath("name"); this.tag.setValue(" Rob Harrop"); @@ -281,7 +281,7 @@ public void withSingleValueAndEditor() throws Exception { } @Test - public void withMultiValueChecked() throws Exception { + void withMultiValueChecked() throws Exception { this.tag.setPath("stringArray"); this.tag.setValue("foo"); int result = this.tag.doStartTag(); @@ -303,7 +303,7 @@ public void withMultiValueChecked() throws Exception { } @Test - public void withMultiValueUnchecked() throws Exception { + void withMultiValueUnchecked() throws Exception { this.tag.setPath("stringArray"); this.tag.setValue("abc"); int result = this.tag.doStartTag(); @@ -325,7 +325,7 @@ public void withMultiValueUnchecked() throws Exception { } @Test - public void withMultiValueWithEditor() throws Exception { + void withMultiValueWithEditor() throws Exception { this.tag.setPath("stringArray"); this.tag.setValue(" foo"); BeanPropertyBindingResult bindingResult = new BeanPropertyBindingResult(this.bean, COMMAND_NAME); @@ -353,7 +353,7 @@ public void withMultiValueWithEditor() throws Exception { } @Test - public void withMultiValueIntegerWithEditor() throws Exception { + void withMultiValueIntegerWithEditor() throws Exception { this.tag.setPath("someIntegerArray"); this.tag.setValue(" 1"); BeanPropertyBindingResult bindingResult = new BeanPropertyBindingResult(this.bean, COMMAND_NAME); @@ -381,7 +381,7 @@ public void withMultiValueIntegerWithEditor() throws Exception { } @Test - public void withCollection() throws Exception { + void withCollection() throws Exception { this.tag.setPath("someList"); this.tag.setValue("foo"); int result = this.tag.doStartTag(); @@ -403,7 +403,7 @@ public void withCollection() throws Exception { } @Test - public void withObjectChecked() throws Exception { + void withObjectChecked() throws Exception { this.tag.setPath("date"); this.tag.setValue(getDate()); @@ -426,7 +426,7 @@ public void withObjectChecked() throws Exception { } @Test - public void withObjectUnchecked() throws Exception { + void withObjectUnchecked() throws Exception { this.tag.setPath("date"); Date date = new Date(); this.tag.setValue(date); @@ -450,7 +450,7 @@ public void withObjectUnchecked() throws Exception { } @Test - public void collectionOfColoursSelected() throws Exception { + void collectionOfColoursSelected() throws Exception { this.tag.setPath("otherColours"); this.tag.setValue("RED"); @@ -472,7 +472,7 @@ public void collectionOfColoursSelected() throws Exception { } @Test - public void collectionOfColoursNotSelected() throws Exception { + void collectionOfColoursNotSelected() throws Exception { this.tag.setPath("otherColours"); this.tag.setValue("PURPLE"); @@ -494,7 +494,7 @@ public void collectionOfColoursNotSelected() throws Exception { } @Test - public void collectionOfPetsAsString() throws Exception { + void collectionOfPetsAsString() throws Exception { this.tag.setPath("pets"); this.tag.setValue("Spot"); @@ -516,7 +516,7 @@ public void collectionOfPetsAsString() throws Exception { } @Test - public void collectionOfPetsAsStringNotSelected() throws Exception { + void collectionOfPetsAsStringNotSelected() throws Exception { this.tag.setPath("pets"); this.tag.setValue("Santa's Little Helper"); @@ -538,7 +538,7 @@ public void collectionOfPetsAsStringNotSelected() throws Exception { } @Test - public void collectionOfPets() throws Exception { + void collectionOfPets() throws Exception { this.tag.setPath("pets"); this.tag.setValue(new Pet("Rudiger")); @@ -561,7 +561,7 @@ public void collectionOfPets() throws Exception { } @Test - public void collectionOfPetsNotSelected() throws Exception { + void collectionOfPetsNotSelected() throws Exception { this.tag.setPath("pets"); this.tag.setValue(new Pet("Santa's Little Helper")); @@ -584,7 +584,7 @@ public void collectionOfPetsNotSelected() throws Exception { } @Test - public void collectionOfPetsWithEditor() throws Exception { + void collectionOfPetsWithEditor() throws Exception { this.tag.setPath("pets"); this.tag.setValue(new ItemPet("Rudiger")); @@ -612,14 +612,14 @@ public void collectionOfPetsWithEditor() throws Exception { } @Test - public void withNullValue() throws Exception { + void withNullValue() throws Exception { this.tag.setPath("name"); assertThatIllegalArgumentException().as("null value binding to a non-boolean").isThrownBy( this.tag::doStartTag); } @Test - public void hiddenElementOmittedOnDisabled() throws Exception { + void hiddenElementOmittedOnDisabled() throws Exception { this.tag.setPath("someBoolean"); this.tag.setDisabled(true); int result = this.tag.doStartTag(); @@ -642,7 +642,7 @@ public void hiddenElementOmittedOnDisabled() throws Exception { } @Test - public void dynamicTypeAttribute() throws JspException { + void dynamicTypeAttribute() throws JspException { assertThatIllegalArgumentException().isThrownBy(() -> this.tag.setDynamicAttribute(null, "type", "email")) .withMessage("Attribute type=\"email\" is not allowed"); @@ -718,7 +718,7 @@ private class MyIntegerEditor extends PropertyEditorSupport { @Override public void setAsText(String text) { this.count++; - setValue(new Integer(text.trim())); + setValue(Integer.valueOf(text.trim())); } } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/form/HiddenInputTagTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/form/HiddenInputTagTests.java index 29c95bda5590..e323aff62bba 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/form/HiddenInputTagTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/form/HiddenInputTagTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -30,7 +30,7 @@ /** * @author Rob Harrop */ -public class HiddenInputTagTests extends AbstractFormTagTests { +class HiddenInputTagTests extends AbstractFormTagTests { private HiddenInputTag tag; @@ -49,7 +49,7 @@ protected TagWriter createTagWriter() { } @Test - public void render() throws Exception { + void render() throws Exception { this.tag.setPath("name"); int result = this.tag.doStartTag(); assertThat(result).isEqualTo(Tag.SKIP_BODY); @@ -65,7 +65,7 @@ public void render() throws Exception { } @Test - public void withCustomBinder() throws Exception { + void withCustomBinder() throws Exception { this.tag.setPath("myFloat"); BeanPropertyBindingResult errors = new BeanPropertyBindingResult(this.bean, COMMAND_NAME); @@ -84,14 +84,14 @@ public void withCustomBinder() throws Exception { } @Test - public void dynamicTypeAttribute() throws JspException { + void dynamicTypeAttribute() throws JspException { assertThatIllegalArgumentException().isThrownBy(() -> this.tag.setDynamicAttribute(null, "type", "email")) .withMessage("Attribute type=\"email\" is not allowed"); } @Test - public void disabledTrue() throws Exception { + void disabledTrue() throws Exception { this.tag.setDisabled(true); this.tag.doStartTag(); @@ -107,7 +107,7 @@ public void disabledTrue() throws Exception { // SPR-8661 @Test - public void disabledFalse() throws Exception { + void disabledFalse() throws Exception { this.tag.setDisabled(false); this.tag.doStartTag(); @@ -132,7 +132,7 @@ private void assertTagOpened(String output) { protected TestBean createTestBean() { this.bean = new TestBean(); bean.setName("Sally Greenwood"); - bean.setMyFloat(new Float("12.34")); + bean.setMyFloat(Float.valueOf("12.34")); return bean; } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/form/InputTagTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/form/InputTagTests.java index a68de172d710..59def204ee51 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/form/InputTagTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/form/InputTagTests.java @@ -56,7 +56,7 @@ protected TestBean createTestBean() { // set up test data this.rob = new TestBean(); this.rob.setName("Rob"); - this.rob.setMyFloat(new Float(12.34)); + this.rob.setMyFloat(Float.valueOf(12.34f)); TestBean sally = new TestBean(); sally.setName("Sally"); diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/form/OptionTagTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/form/OptionTagTests.java index 54de88290b91..a94bee41a7d7 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/form/OptionTagTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/form/OptionTagTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -46,7 +46,7 @@ * @author Jeremy Grelle */ @SuppressWarnings({ "rawtypes", "unchecked" }) -public class OptionTagTests extends AbstractHtmlElementTagTests { +class OptionTagTests extends AbstractHtmlElementTagTests { private static final String ARRAY_SOURCE = "abc,123,def"; @@ -79,7 +79,7 @@ public String getName() { @Test - public void canBeDisabledEvenWhenSelected() throws Exception { + void canBeDisabledEvenWhenSelected() throws Exception { String selectName = "testBean.name"; BindStatus bindStatus = new BindStatus(getRequestContext(), selectName, false); getPageContext().setAttribute(SelectTag.LIST_VALUE_PAGE_ATTRIBUTE, bindStatus); @@ -101,7 +101,7 @@ public void canBeDisabledEvenWhenSelected() throws Exception { } @Test - public void renderNotSelected() throws Exception { + void renderNotSelected() throws Exception { String selectName = "testBean.name"; BindStatus bindStatus = new BindStatus(getRequestContext(), selectName, false); getPageContext().setAttribute(SelectTag.LIST_VALUE_PAGE_ATTRIBUTE, bindStatus); @@ -121,7 +121,7 @@ public void renderNotSelected() throws Exception { } @Test - public void renderWithDynamicAttributes() throws Exception { + void renderWithDynamicAttributes() throws Exception { String dynamicAttribute1 = "attr1"; String dynamicAttribute2 = "attr2"; @@ -149,7 +149,7 @@ public void renderWithDynamicAttributes() throws Exception { } @Test - public void renderSelected() throws Exception { + void renderSelected() throws Exception { String selectName = "testBean.name"; BindStatus bindStatus = new BindStatus(getRequestContext(), selectName, false); getPageContext().setAttribute(SelectTag.LIST_VALUE_PAGE_ATTRIBUTE, bindStatus); @@ -172,7 +172,7 @@ public void renderSelected() throws Exception { } @Test - public void withNoLabel() throws Exception { + void withNoLabel() throws Exception { String selectName = "testBean.name"; BindStatus bindStatus = new BindStatus(getRequestContext(), selectName, false); getPageContext().setAttribute(SelectTag.LIST_VALUE_PAGE_ATTRIBUTE, bindStatus); @@ -195,7 +195,7 @@ public void withNoLabel() throws Exception { } @Test - public void withoutContext() throws Exception { + void withoutContext() throws Exception { this.tag.setParent(null); this.tag.setValue("foo"); this.tag.setLabel("Foo"); @@ -204,7 +204,7 @@ public void withoutContext() throws Exception { } @Test - public void withPropertyEditor() throws Exception { + void withPropertyEditor() throws Exception { String selectName = "testBean.stringArray"; BindStatus bindStatus = new BindStatus(getRequestContext(), selectName, false) { @Override @@ -233,7 +233,7 @@ public PropertyEditor getEditor() { } @Test - public void withPropertyEditorStringComparison() throws Exception { + void withPropertyEditorStringComparison() throws Exception { final PropertyEditor testBeanEditor = new TestBeanPropertyEditor(); testBeanEditor.setValue(new TestBean("Sally")); String selectName = "testBean.spouse"; @@ -261,11 +261,11 @@ public PropertyEditor getEditor() { } @Test - public void withCustomObjectSelected() throws Exception { + void withCustomObjectSelected() throws Exception { String selectName = "testBean.someNumber"; BindStatus bindStatus = new BindStatus(getRequestContext(), selectName, false); getPageContext().setAttribute(SelectTag.LIST_VALUE_PAGE_ATTRIBUTE, bindStatus); - this.tag.setValue(new Float(12.34)); + this.tag.setValue(12.34f); this.tag.setLabel("GBP 12.34"); int result = this.tag.doStartTag(); assertThat(result).isEqualTo(BodyTag.EVAL_BODY_BUFFERED); @@ -282,11 +282,11 @@ public void withCustomObjectSelected() throws Exception { } @Test - public void withCustomObjectNotSelected() throws Exception { + void withCustomObjectNotSelected() throws Exception { String selectName = "testBean.someNumber"; BindStatus bindStatus = new BindStatus(getRequestContext(), selectName, false); getPageContext().setAttribute(SelectTag.LIST_VALUE_PAGE_ATTRIBUTE, bindStatus); - this.tag.setValue(new Float(12.35)); + this.tag.setValue(12.35f); this.tag.setLabel("GBP 12.35"); int result = this.tag.doStartTag(); assertThat(result).isEqualTo(BodyTag.EVAL_BODY_BUFFERED); @@ -303,9 +303,9 @@ public void withCustomObjectNotSelected() throws Exception { } @Test - public void withCustomObjectAndEditorSelected() throws Exception { + void withCustomObjectAndEditorSelected() throws Exception { final PropertyEditor floatEditor = new SimpleFloatEditor(); - floatEditor.setValue(new Float("12.34")); + floatEditor.setValue(Float.valueOf("12.34")); String selectName = "testBean.someNumber"; BindStatus bindStatus = new BindStatus(getRequestContext(), selectName, false) { @Override @@ -315,7 +315,7 @@ public PropertyEditor getEditor() { }; getPageContext().setAttribute(SelectTag.LIST_VALUE_PAGE_ATTRIBUTE, bindStatus); - this.tag.setValue(new Float(12.34)); + this.tag.setValue(12.34f); this.tag.setLabel("12.34f"); int result = this.tag.doStartTag(); @@ -331,7 +331,7 @@ public PropertyEditor getEditor() { } @Test - public void withCustomObjectAndEditorNotSelected() throws Exception { + void withCustomObjectAndEditorNotSelected() throws Exception { final PropertyEditor floatEditor = new SimpleFloatEditor(); String selectName = "testBean.someNumber"; BindStatus bindStatus = new BindStatus(getRequestContext(), selectName, false) { @@ -342,7 +342,7 @@ public PropertyEditor getEditor() { }; getPageContext().setAttribute(SelectTag.LIST_VALUE_PAGE_ATTRIBUTE, bindStatus); - this.tag.setValue(new Float(12.35)); + this.tag.setValue(12.35f); this.tag.setLabel("12.35f"); int result = this.tag.doStartTag(); @@ -358,7 +358,7 @@ public PropertyEditor getEditor() { } @Test - public void asBodyTag() throws Exception { + void asBodyTag() throws Exception { String selectName = "testBean.name"; BindStatus bindStatus = new BindStatus(getRequestContext(), selectName, false); getPageContext().setAttribute(SelectTag.LIST_VALUE_PAGE_ATTRIBUTE, bindStatus); @@ -380,7 +380,7 @@ public void asBodyTag() throws Exception { } @Test - public void asBodyTagSelected() throws Exception { + void asBodyTagSelected() throws Exception { String selectName = "testBean.name"; BindStatus bindStatus = new BindStatus(getRequestContext(), selectName, false); getPageContext().setAttribute(SelectTag.LIST_VALUE_PAGE_ATTRIBUTE, bindStatus); @@ -401,7 +401,7 @@ public void asBodyTagSelected() throws Exception { } @Test - public void asBodyTagCollapsed() throws Exception { + void asBodyTagCollapsed() throws Exception { String selectName = "testBean.name"; BindStatus bindStatus = new BindStatus(getRequestContext(), selectName, false); getPageContext().setAttribute(SelectTag.LIST_VALUE_PAGE_ATTRIBUTE, bindStatus); @@ -423,7 +423,7 @@ public void asBodyTagCollapsed() throws Exception { } @Test - public void asBodyTagWithEditor() throws Exception { + void asBodyTagWithEditor() throws Exception { String selectName = "testBean.stringArray"; BindStatus bindStatus = new BindStatus(getRequestContext(), selectName, false) { @Override @@ -447,7 +447,7 @@ public PropertyEditor getEditor() { } @Test - public void multiBind() throws Exception { + void multiBind() throws Exception { BeanPropertyBindingResult result = new BeanPropertyBindingResult(new TestBean(), "testBean"); result.getPropertyAccessor().registerCustomEditor(TestBean.class, "friends", new FriendEditor()); exposeBindingResult(result); @@ -463,7 +463,7 @@ public void multiBind() throws Exception { } @Test - public void optionTagNotNestedWithinSelectTag() throws Exception { + void optionTagNotNestedWithinSelectTag() throws Exception { tag.setParent(null); tag.setValue("foo"); assertThatIllegalStateException().as("when not nested within a