Commit d4c91d2f authored by sdeleuze's avatar sdeleuze Committed by Stephane Nicoll

Improve Kotlin extensions doc about type erasure

Since type erasure can be fixed only when using
ParameterizedTypeReference based Java methods, TestRestTemplate
API documentation should be updated to specify which extensions
are subject to type erasure, and which are not.

Closes gh-11604
parent b7a99335
...@@ -25,8 +25,10 @@ import org.springframework.web.client.RestClientException ...@@ -25,8 +25,10 @@ import org.springframework.web.client.RestClientException
import java.net.URI import java.net.URI
/** /**
* Extension for [TestRestTemplate.getForObject] avoiding specifying the type * Extension for [TestRestTemplate.getForObject] providing a `getForObject<Foo>(...)`
* parameter thanks to Kotlin reified type parameters. * variant leveraging Kotlin reified type parameters. Like the original Java method, this
* extension is subject to type erasure. Use [exchange] if you need to retain actual
* generic type arguments.
* *
* @author Sebastien Deleuze * @author Sebastien Deleuze
* @since 2.0.0 * @since 2.0.0
...@@ -36,8 +38,10 @@ inline fun <reified T : Any> TestRestTemplate.getForObject(url: String, vararg u ...@@ -36,8 +38,10 @@ inline fun <reified T : Any> TestRestTemplate.getForObject(url: String, vararg u
getForObject(url, T::class.java, *uriVariables) getForObject(url, T::class.java, *uriVariables)
/** /**
* Extension for [TestRestTemplate.getForObject] avoiding specifying the type * Extension for [TestRestTemplate.getForObject] providing a `getForObject<Foo>(...)`
* parameter thanks to Kotlin reified type parameters. * variant leveraging Kotlin reified type parameters. Like the original Java method, this
* extension is subject to type erasure. Use [exchange] if you need to retain actual
* generic type arguments.
* *
* @author Sebastien Deleuze * @author Sebastien Deleuze
* @since 2.0.0 * @since 2.0.0
...@@ -47,8 +51,10 @@ inline fun <reified T : Any> TestRestTemplate.getForObject(url: String, uriVaria ...@@ -47,8 +51,10 @@ inline fun <reified T : Any> TestRestTemplate.getForObject(url: String, uriVaria
getForObject(url, T::class.java, uriVariables) getForObject(url, T::class.java, uriVariables)
/** /**
* Extension for [TestRestTemplate.getForObject] avoiding specifying the type parameter * Extension for [TestRestTemplate.getForObject] providing a `getForObject<Foo>(...)`
* thanks to Kotlin reified type parameters. * variant leveraging Kotlin reified type parameters. Like the original Java method, this
* extension is subject to type erasure. Use [exchange] if you need to retain actual
* generic type arguments.
* *
* @author Sebastien Deleuze * @author Sebastien Deleuze
* @since 2.0.0 * @since 2.0.0
...@@ -58,8 +64,10 @@ inline fun <reified T : Any> TestRestTemplate.getForObject(url: URI): T? = ...@@ -58,8 +64,10 @@ inline fun <reified T : Any> TestRestTemplate.getForObject(url: URI): T? =
getForObject(url, T::class.java) getForObject(url, T::class.java)
/** /**
* Extension for [TestRestTemplate.getForEntity] avoiding requiring the type parameter * Extension for [TestRestTemplate.getForEntity] providing a `getForEntity<Foo>(...)`
* thanks to Kotlin reified type parameters. * variant leveraging Kotlin reified type parameters. Like the original Java method, this
* extension is subject to type erasure. Use [exchange] if you need to retain actual
* generic type arguments.
* *
* @author Sebastien Deleuze * @author Sebastien Deleuze
* @since 2.0.0 * @since 2.0.0
...@@ -69,8 +77,10 @@ inline fun <reified T : Any> TestRestTemplate.getForEntity(url: URI): ResponseEn ...@@ -69,8 +77,10 @@ inline fun <reified T : Any> TestRestTemplate.getForEntity(url: URI): ResponseEn
getForEntity(url, T::class.java) getForEntity(url, T::class.java)
/** /**
* Extension for [TestRestTemplate.getForEntity] avoiding requiring the type parameter * Extension for [TestRestTemplate.getForEntity] providing a `getForEntity<Foo>(...)`
* thanks to Kotlin reified type parameters. * variant leveraging Kotlin reified type parameters. Like the original Java method, this
* extension is subject to type erasure. Use [exchange] if you need to retain actual
* generic type arguments.
* *
* @author Sebastien Deleuze * @author Sebastien Deleuze
* @since 2.0.0 * @since 2.0.0
...@@ -80,8 +90,10 @@ inline fun <reified T : Any> TestRestTemplate.getForEntity(url: String, vararg u ...@@ -80,8 +90,10 @@ inline fun <reified T : Any> TestRestTemplate.getForEntity(url: String, vararg u
getForEntity(url, T::class.java, *uriVariables) getForEntity(url, T::class.java, *uriVariables)
/** /**
* Extension for [TestRestTemplate.getForEntity] avoiding requiring the type parameter * Extension for [TestRestTemplate.getForEntity] providing a `getForEntity<Foo>(...)`
* thanks to Kotlin reified type parameters. * variant leveraging Kotlin reified type parameters. Like the original Java method, this
* extension is subject to type erasure. Use [exchange] if you need to retain actual
* generic type arguments.
* *
* @author Sebastien Deleuze * @author Sebastien Deleuze
* @since 2.0.0 * @since 2.0.0
...@@ -91,140 +103,171 @@ inline fun <reified T : Any> TestRestTemplate.getForEntity(url: String, uriVaria ...@@ -91,140 +103,171 @@ inline fun <reified T : Any> TestRestTemplate.getForEntity(url: String, uriVaria
getForEntity(url, T::class.java, uriVariables) getForEntity(url, T::class.java, uriVariables)
/** /**
* Extension for [TestRestTemplate.patchForObject] avoiding specifying the type parameter * Extension for [TestRestTemplate.patchForObject] providing a `patchForObject<Foo>(...)`
* thanks to Kotlin reified type parameters. * variant leveraging Kotlin reified type parameters. Like the original Java method, this
* extension is subject to type erasure. Use [exchange] if you need to retain actual
* generic type arguments.
* *
* @author Sebastien Deleuze * @author Sebastien Deleuze
* @since 2.0.0 * @since 2.0.0
*/ */
@Throws(RestClientException::class) @Throws(RestClientException::class)
inline fun <reified T : Any> TestRestTemplate.patchForObject(url: String, request: Any, vararg uriVariables: Any): T? = inline fun <reified T : Any> TestRestTemplate.patchForObject(url: String, request: Any? = null,
vararg uriVariables: Any): T? =
patchForObject(url, request, T::class.java, *uriVariables) patchForObject(url, request, T::class.java, *uriVariables)
/** /**
* Extension for [TestRestTemplate.patchForObject] avoiding specifying the type parameter * Extension for [TestRestTemplate.patchForObject] providing a `patchForObject<Foo>(...)`
* thanks to Kotlin reified type parameters. * variant leveraging Kotlin reified type parameters. Like the original Java method, this
* extension is subject to type erasure. Use [exchange] if you need to retain actual
* generic type arguments.
* *
* @author Sebastien Deleuze * @author Sebastien Deleuze
* @since 2.0.0 * @since 2.0.0
*/ */
@Throws(RestClientException::class) @Throws(RestClientException::class)
inline fun <reified T : Any> TestRestTemplate.patchForObject(url: String, request: Any, uriVariables: Map<String, *>): T? = inline fun <reified T : Any> TestRestTemplate.patchForObject(url: String, request: Any? = null,
uriVariables: Map<String, *>): T? =
patchForObject(url, request, T::class.java, uriVariables) patchForObject(url, request, T::class.java, uriVariables)
/** /**
* Extension for [TestRestTemplate.patchForObject] avoiding specifying the type parameter * Extension for [TestRestTemplate.patchForObject] providing a `patchForObject<Foo>(...)`
* thanks to Kotlin reified type parameters. * variant leveraging Kotlin reified type parameters. Like the original Java method, this
* extension is subject to type erasure. Use [exchange] if you need to retain actual
* generic type arguments.
* *
* @author Sebastien Deleuze * @author Sebastien Deleuze
* @since 2.0.0 * @since 2.0.0
*/ */
@Throws(RestClientException::class) @Throws(RestClientException::class)
inline fun <reified T : Any> TestRestTemplate.patchForObject(url: URI, request: Any): T? = inline fun <reified T : Any> TestRestTemplate.patchForObject(url: URI, request: Any? = null): T? =
patchForObject(url, request, T::class.java) patchForObject(url, request, T::class.java)
/** /**
* Extension for [TestRestTemplate.postForObject] avoiding specifying the type parameter * Extension for [TestRestTemplate.postForObject] providing a `postForObject<Foo>(...)`
* thanks to Kotlin reified type parameters. * variant leveraging Kotlin reified type parameters. Like the original Java method, this
* extension is subject to type erasure. Use [exchange] if you need to retain actual
* generic type arguments.
* *
* @author Sebastien Deleuze * @author Sebastien Deleuze
* @since 2.0.0 * @since 2.0.0
*/ */
@Throws(RestClientException::class) @Throws(RestClientException::class)
inline fun <reified T : Any> TestRestTemplate.postForObject(url: String, request: Any, vararg uriVariables: Any): T? = inline fun <reified T : Any> TestRestTemplate.postForObject(url: String, request: Any? = null,
vararg uriVariables: Any): T? =
postForObject(url, request, T::class.java, *uriVariables) postForObject(url, request, T::class.java, *uriVariables)
/** /**
* Extension for [TestRestTemplate.postForObject] avoiding specifying the type parameter * Extension for [TestRestTemplate.postForObject] providing a `postForObject<Foo>(...)`
* thanks to Kotlin reified type parameters. * variant leveraging Kotlin reified type parameters. Like the original Java method, this
* extension is subject to type erasure. Use [exchange] if you need to retain actual
* generic type arguments.
* *
* @author Sebastien Deleuze * @author Sebastien Deleuze
* @since 2.0.0 * @since 2.0.0
*/ */
@Throws(RestClientException::class) @Throws(RestClientException::class)
inline fun <reified T : Any> TestRestTemplate.postForObject(url: String, request: Any, uriVariables: Map<String, *>): T? = inline fun <reified T : Any> TestRestTemplate.postForObject(url: String, request: Any? = null,
uriVariables: Map<String, *>): T? =
postForObject(url, request, T::class.java, uriVariables) postForObject(url, request, T::class.java, uriVariables)
/** /**
* Extension for [TestRestTemplate.postForObject] avoiding specifying the type parameter * Extension for [TestRestTemplate.postForObject] providing a `postForObject<Foo>(...)`
* thanks to Kotlin reified type parameters. * variant leveraging Kotlin reified type parameters. Like the original Java method, this
* extension is subject to type erasure. Use [exchange] if you need to retain actual
* generic type arguments.
* *
* @author Sebastien Deleuze * @author Sebastien Deleuze
* @since 2.0.0 * @since 2.0.0
*/ */
@Throws(RestClientException::class) @Throws(RestClientException::class)
inline fun <reified T : Any> TestRestTemplate.postForObject(url: URI, request: Any): T? = inline fun <reified T : Any> TestRestTemplate.postForObject(url: URI, request: Any? = null): T? =
postForObject(url, request, T::class.java) postForObject(url, request, T::class.java)
/** /**
* Extension for [TestRestTemplate.postForEntity] avoiding specifying the type parameter * Extension for [TestRestTemplate.postForEntity] providing a `postForEntity<Foo>(...)`
* thanks to Kotlin reified type parameters. * variant leveraging Kotlin reified type parameters. Like the original Java method, this
* extension is subject to type erasure. Use [exchange] if you need to retain actual
* generic type arguments.
* *
* @author Sebastien Deleuze * @author Sebastien Deleuze
* @since 2.0.0 * @since 2.0.0
*/ */
@Throws(RestClientException::class) @Throws(RestClientException::class)
inline fun <reified T : Any> TestRestTemplate.postForEntity(url: String, request: Any, vararg uriVariables: Any): ResponseEntity<T> = inline fun <reified T : Any> TestRestTemplate.postForEntity(url: String, request: Any? = null,
vararg uriVariables: Any): ResponseEntity<T> =
postForEntity(url, request, T::class.java, *uriVariables) postForEntity(url, request, T::class.java, *uriVariables)
/** /**
* Extension for [TestRestTemplate.postForEntity] avoiding specifying the type parameter * Extension for [TestRestTemplate.postForEntity] providing a `postForEntity<Foo>(...)`
* thanks to Kotlin reified type parameters. * variant leveraging Kotlin reified type parameters. Like the original Java method, this
* extension is subject to type erasure. Use [exchange] if you need to retain actual
* generic type arguments.
* *
* @author Sebastien Deleuze * @author Sebastien Deleuze
* @since 2.0.0 * @since 2.0.0
*/ */
@Throws(RestClientException::class) @Throws(RestClientException::class)
inline fun <reified T : Any> TestRestTemplate.postForEntity(url: String, request: Any, uriVariables: Map<String, *>): ResponseEntity<T> = inline fun <reified T : Any> TestRestTemplate.postForEntity(url: String, request: Any? = null,
uriVariables: Map<String, *>): ResponseEntity<T> =
postForEntity(url, request, T::class.java, uriVariables) postForEntity(url, request, T::class.java, uriVariables)
/** /**
* Extension for [TestRestTemplate.postForEntity] avoiding specifying the type parameter * Extension for [TestRestTemplate.postForEntity] providing a `postForEntity<Foo>(...)`
* thanks to Kotlin reified type parameters. * variant leveraging Kotlin reified type parameters. Like the original Java method, this
* extension is subject to type erasure. Use [exchange] if you need to retain actual
* generic type arguments.
* *
* @author Sebastien Deleuze * @author Sebastien Deleuze
* @since 2.0.0 * @since 2.0.0
*/ */
@Throws(RestClientException::class) @Throws(RestClientException::class)
inline fun <reified T : Any> TestRestTemplate.postForEntity(url: URI, request: Any): ResponseEntity<T> = inline fun <reified T : Any> TestRestTemplate.postForEntity(url: URI, request: Any? = null): ResponseEntity<T> =
postForEntity(url, request, T::class.java) postForEntity(url, request, T::class.java)
/** /**
* Extension for [TestRestTemplate.exchange] avoiding specifying the type parameter * Extension for [TestRestTemplate.exchange] providing an `exchange<Foo>(...)`
* thanks to Kotlin reified type parameters. * variant leveraging Kotlin reified type parameters. This extension is not subject to
* type erasure and retains actual generic type arguments.
* *
* @author Sebastien Deleuze * @author Sebastien Deleuze
* @since 2.0.0 * @since 2.0.0
*/ */
@Throws(RestClientException::class) @Throws(RestClientException::class)
inline fun <reified T : Any> TestRestTemplate.exchange(url: String, method: HttpMethod, requestEntity: HttpEntity<*>, vararg uriVariables: Any): ResponseEntity<T> = inline fun <reified T : Any> TestRestTemplate.exchange(url: String, method: HttpMethod,
requestEntity: HttpEntity<*>? = null, vararg uriVariables: Any): ResponseEntity<T> =
exchange(url, method, requestEntity, object : ParameterizedTypeReference<T>() {}, *uriVariables) exchange(url, method, requestEntity, object : ParameterizedTypeReference<T>() {}, *uriVariables)
/** /**
* Extension for [TestRestTemplate.exchange] avoiding specifying the type parameter * Extension for [TestRestTemplate.exchange] providing an `exchange<Foo>(...)`
* thanks to Kotlin reified type parameters. * variant leveraging Kotlin reified type parameters. This extension is not subject to
* type erasure and retains actual generic type arguments.
* *
* @author Sebastien Deleuze * @author Sebastien Deleuze
* @since 2.0.0 * @since 2.0.0
*/ */
@Throws(RestClientException::class) @Throws(RestClientException::class)
inline fun <reified T : Any> TestRestTemplate.exchange(url: String, method: HttpMethod, requestEntity: HttpEntity<*>, uriVariables: Map<String, *>): ResponseEntity<T> = inline fun <reified T : Any> TestRestTemplate.exchange(url: String, method: HttpMethod,
requestEntity: HttpEntity<*>? = null, uriVariables: Map<String, *>): ResponseEntity<T> =
exchange(url, method, requestEntity, object : ParameterizedTypeReference<T>() {}, uriVariables) exchange(url, method, requestEntity, object : ParameterizedTypeReference<T>() {}, uriVariables)
/** /**
* Extension for [TestRestTemplate.exchange] avoiding specifying the type parameter * Extension for [TestRestTemplate.exchange] providing an `exchange<Foo>(...)`
* thanks to Kotlin reified type parameters. * variant leveraging Kotlin reified type parameters. This extension is not subject to
* type erasure and retains actual generic type arguments.
* *
* @author Sebastien Deleuze * @author Sebastien Deleuze
* @since 2.0.0 * @since 2.0.0
*/ */
@Throws(RestClientException::class) @Throws(RestClientException::class)
inline fun <reified T : Any> TestRestTemplate.exchange(url: URI, method: HttpMethod, requestEntity: HttpEntity<*>): ResponseEntity<T> = inline fun <reified T : Any> TestRestTemplate.exchange(url: URI, method: HttpMethod,
requestEntity: HttpEntity<*>? = null): ResponseEntity<T> =
exchange(url, method, requestEntity, object : ParameterizedTypeReference<T>() {}) exchange(url, method, requestEntity, object : ParameterizedTypeReference<T>() {})
/** /**
* Extension for [TestRestTemplate.exchange] avoiding specifying the type parameter * Extension for [TestRestTemplate.exchange] providing an `exchange<Foo>(...)`
* thanks to Kotlin reified type parameters. * variant leveraging Kotlin reified type parameters. This extension is not subject to
* type erasure and retains actual generic type arguments.
* *
* @author Sebastien Deleuze * @author Sebastien Deleuze
* @since 2.0.0 * @since 2.0.0
......
...@@ -122,6 +122,13 @@ class TestRestTemplateExtensionsTests { ...@@ -122,6 +122,13 @@ class TestRestTemplateExtensionsTests {
verify(template, times(1)).patchForObject(url, body, Foo::class.java) verify(template, times(1)).patchForObject(url, body, Foo::class.java)
} }
@Test
fun `patchForObject with reified type parameters`() {
val url = "https://spring.io"
template.patchForObject<Foo>(url)
verify(template, times(1)).patchForObject(url, null, Foo::class.java)
}
@Test @Test
fun `postForObject with reified type parameters, String, Any and varargs`() { fun `postForObject with reified type parameters, String, Any and varargs`() {
val url = "https://spring.io" val url = "https://spring.io"
...@@ -149,6 +156,13 @@ class TestRestTemplateExtensionsTests { ...@@ -149,6 +156,13 @@ class TestRestTemplateExtensionsTests {
verify(template, times(1)).postForObject(url, body, Foo::class.java) verify(template, times(1)).postForObject(url, body, Foo::class.java)
} }
@Test
fun `postForObject with reified type parameters`() {
val url = "https://spring.io"
template.postForObject<Foo>(url)
verify(template, times(1)).postForObject(url, null, Foo::class.java)
}
@Test @Test
fun `postForEntity with reified type parameters, String, Any and varargs`() { fun `postForEntity with reified type parameters, String, Any and varargs`() {
val url = "https://spring.io" val url = "https://spring.io"
...@@ -176,6 +190,13 @@ class TestRestTemplateExtensionsTests { ...@@ -176,6 +190,13 @@ class TestRestTemplateExtensionsTests {
verify(template, times(1)).postForEntity(url, body, Foo::class.java) verify(template, times(1)).postForEntity(url, body, Foo::class.java)
} }
@Test
fun `postForEntity with reified type parameters`() {
val url = "https://spring.io"
template.postForEntity<Foo>(url)
verify(template, times(1)).postForEntity(url, null, Foo::class.java)
}
@Test @Test
fun `exchange with reified type parameters, String, HttpMethod, HttpEntity and varargs`() { fun `exchange with reified type parameters, String, HttpMethod, HttpEntity and varargs`() {
val url = "https://spring.io" val url = "https://spring.io"
...@@ -217,6 +238,15 @@ class TestRestTemplateExtensionsTests { ...@@ -217,6 +238,15 @@ class TestRestTemplateExtensionsTests {
object : ParameterizedTypeReference<List<Foo>>() {}) object : ParameterizedTypeReference<List<Foo>>() {})
} }
@Test
fun `exchange with reified type parameters, String and HttpMethod`() {
val url = "https://spring.io"
val method = HttpMethod.GET
template.exchange<List<Foo>>(url, method)
verify(template, times(1)).exchange(url, method, null,
object : ParameterizedTypeReference<List<Foo>>() {})
}
@Test @Test
fun `RestOperations are available`() { fun `RestOperations are available`() {
val extensions = Class.forName( val extensions = Class.forName(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment