diff --git a/spring-web/src/main/kotlin/org/springframework/web/client/RestOperationsExtensions.kt b/spring-web/src/main/kotlin/org/springframework/web/client/RestOperationsExtensions.kt index 621407626b..70a00f03ba 100644 --- a/spring-web/src/main/kotlin/org/springframework/web/client/RestOperationsExtensions.kt +++ b/spring-web/src/main/kotlin/org/springframework/web/client/RestOperationsExtensions.kt @@ -59,6 +59,17 @@ inline fun RestOperations.getForObject(url: String, uriVariable inline fun RestOperations.getForObject(url: URI): T? = getForObject(url, T::class.java) +/** + * Extension for [RestOperations.getForEntity] avoiding requiring the type parameter + * thanks to Kotlin reified type parameters. + * + * @author Sebastien Deleuze + * @since 5.0.2 + */ +@Throws(RestClientException::class) +inline fun RestOperations.getForEntity(url: URI): ResponseEntity = + getForEntity(url, T::class.java) + /** * Extension for [RestOperations.getForEntity] avoiding requiring the type parameter * thanks to Kotlin reified type parameters. @@ -71,6 +82,50 @@ inline fun RestOperations.getForObject(url: URI): T? = inline fun RestOperations.getForEntity(url: String, vararg uriVariables: Any): ResponseEntity = getForEntity(url, T::class.java, *uriVariables) +/** + * Extension for [RestOperations.getForEntity] avoiding requiring the type parameter + * thanks to Kotlin reified type parameters. + * + * @author Sebastien Deleuze + * @since 5.0.2 + */ +@Throws(RestClientException::class) +inline fun RestOperations.getForEntity(url: String, uriVariables: Map): ResponseEntity = + getForEntity(url, T::class.java, uriVariables) + +/** + * Extension for [RestOperations.patchForObject] avoiding specifying the type parameter + * thanks to Kotlin reified type parameters. + * + * @author Sebastien Deleuze + * @since 5.0.2 + */ +@Throws(RestClientException::class) +inline fun RestOperations.patchForObject(url: String, request: Any, vararg uriVariables: Any): T? = + patchForObject(url, request, T::class.java, *uriVariables) + +/** + * Extension for [RestOperations.patchForObject] avoiding specifying the type parameter + * thanks to Kotlin reified type parameters. + * + * @author Sebastien Deleuze + * @since 5.0.2 + */ +@Throws(RestClientException::class) +inline fun RestOperations.patchForObject(url: String, request: Any, uriVariables: Map): T? = + patchForObject(url, request, T::class.java, uriVariables) + +/** + * Extension for [RestOperations.patchForObject] avoiding specifying the type parameter + * thanks to Kotlin reified type parameters. + * + * @author Sebastien Deleuze + * @since 5.0.2 + */ +@Throws(RestClientException::class) +inline fun RestOperations.patchForObject(url: URI, request: Any): T? = + patchForObject(url, request, T::class.java) + /** * Extension for [RestOperations.postForObject] avoiding specifying the type parameter * thanks to Kotlin reified type parameters. diff --git a/spring-web/src/test/kotlin/org/springframework/web/client/RestOperationsExtensionsTests.kt b/spring-web/src/test/kotlin/org/springframework/web/client/RestOperationsExtensionsTests.kt index 18878b9b32..6b0e42e399 100644 --- a/spring-web/src/test/kotlin/org/springframework/web/client/RestOperationsExtensionsTests.kt +++ b/spring-web/src/test/kotlin/org/springframework/web/client/RestOperationsExtensionsTests.kt @@ -17,6 +17,7 @@ package org.springframework.web.client import com.nhaarman.mockito_kotlin.mock +import org.junit.Assert import org.junit.Test import org.junit.runner.RunWith import org.mockito.Answers @@ -27,7 +28,10 @@ import org.springframework.core.ParameterizedTypeReference import org.springframework.http.HttpEntity import org.springframework.http.HttpMethod import org.springframework.http.RequestEntity +import org.springframework.util.ReflectionUtils import java.net.URI +import kotlin.reflect.full.createType +import kotlin.reflect.jvm.kotlinFunction /** * Mock object based tests for [RestOperations] Kotlin extensions. @@ -64,6 +68,13 @@ class RestOperationsExtensionsTests { verify(template, times(1)).getForObject(url, Foo::class.java) } + @Test + fun `getForEntity with reified type parameters, String and URI`() { + val url = URI("https://spring.io") + template.getForEntity(url) + verify(template, times(1)).getForEntity(url, Foo::class.java) + } + @Test fun `getForEntity with reified type parameters, String and varargs`() { val url = "https://spring.io" @@ -73,6 +84,41 @@ class RestOperationsExtensionsTests { verify(template, times(1)).getForEntity(url, Foo::class.java, var1, var2) } + @Test + fun `getForEntity with reified type parameters and Map`() { + val url = "https://spring.io" + val vars = mapOf(Pair("key1", "value1"), Pair("key2", "value2")) + template.getForEntity(url, vars) + verify(template, times(1)).getForEntity(url, Foo::class.java, vars) + } + + @Test + fun `patchForObject with reified type parameters, String and varargs`() { + val url = "https://spring.io" + val body: Any = "body" + val var1 = "var1" + val var2 = "var2" + template.patchForObject(url, body, var1, var2) + verify(template, times(1)).patchForObject(url, body, Foo::class.java, var1, var2) + } + + @Test + fun `patchForObject with reified type parameters, String and Map`() { + val url = "https://spring.io" + val body: Any = "body" + val vars = mapOf(Pair("key1", "value1"), Pair("key2", "value2")) + template.patchForObject(url, body, vars) + verify(template, times(1)).patchForObject(url, body, Foo::class.java, vars) + } + + @Test + fun `patchForObject with reified type parameters`() { + val url = "https://spring.io" + val body: Any = "body" + template.patchForObject(url, body) + verify(template, times(1)).patchForObject(url, body, Foo::class.java) + } + @Test fun `postForObject with reified type parameters, String and varargs`() { val url = "https://spring.io" @@ -168,6 +214,21 @@ class RestOperationsExtensionsTests { object : ParameterizedTypeReference>() {}) } + @Test + fun `RestOperations are available`() { + val extensions = Class.forName("org.springframework.web.client.RestOperationsExtensionsKt") + ReflectionUtils.doWithMethods(RestOperations::class.java) { method -> + arrayOf(ParameterizedTypeReference::class, Class::class).forEach { kClass -> + if (method.parameterTypes.contains(kClass.java)) { + val parameters = mutableListOf>(RestOperations::class.java).apply { addAll(method.parameterTypes.filter { it != kClass.java }) } + val f = extensions.getDeclaredMethod(method.name, *parameters.toTypedArray()).kotlinFunction!! + Assert.assertEquals(1, f.typeParameters.size) + Assert.assertEquals(listOf(Any::class.createType()), f.typeParameters[0].upperBounds) + } + } + } + } + class Foo }