-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
There is an issue in 2.8.2 when serializing an empty string to a non-null field in Kotlin. This works in 2.8.1, and was exposed by the eclipsestore guide https://github.com/micronaut-projects/micronaut-guides/pull/1443\#commits-pushed-0276ab1
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package example; | ||
|
||
import io.micronaut.core.annotation.Nullable; | ||
import io.micronaut.serde.annotation.Serdeable; | ||
import jakarta.validation.constraints.NotEmpty; | ||
|
||
@Serdeable | ||
record FruitCommand( | ||
@NotEmpty String name, @Nullable String description | ||
) {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,4 +11,4 @@ | |
<root level="info"> | ||
<appender-ref ref="STDOUT" /> | ||
</root> | ||
</configuration> | ||
</configuration> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package example; | ||
|
||
import io.micronaut.context.annotation.Property; | ||
import io.micronaut.context.annotation.Requires; | ||
import io.micronaut.http.HttpRequest; | ||
import io.micronaut.http.annotation.Body; | ||
import io.micronaut.http.annotation.Controller; | ||
import io.micronaut.http.annotation.Post; | ||
import io.micronaut.http.client.HttpClient; | ||
import io.micronaut.http.client.exceptions.HttpClientResponseException; | ||
import io.micronaut.runtime.server.EmbeddedServer; | ||
import io.micronaut.test.extensions.junit5.annotation.MicronautTest; | ||
import jakarta.validation.Valid; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import java.util.List; | ||
import java.util.Map; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.junit.jupiter.api.Assertions.assertThrows; | ||
|
||
@MicronautTest | ||
@Property(name = "spec.name", value = "FruitCommandTest") | ||
class FruitCommandTest { | ||
|
||
@Test | ||
void testCommandPost(EmbeddedServer embeddedServer) { | ||
try(var client = embeddedServer.getApplicationContext().createBean(HttpClient.class, embeddedServer.getURL())) { | ||
var ex = assertThrows( | ||
HttpClientResponseException.class, | ||
() -> client.toBlocking().exchange(HttpRequest.POST("/fruits", new FruitCommand("", "")), String.class) | ||
); | ||
Map<String, Object> embedded = (Map<String, Object>) ex.getResponse().getBody(Map.class).get().get("_embedded"); | ||
Check failure on line 33 in doc-examples/example-java/src/test/java/example/FruitCommandTest.java GitHub Actions / Java CI / Test Report (17)FruitCommandTest.testCommandPost(EmbeddedServer)
Raw output
Check failure on line 33 in doc-examples/example-java/src/test/java/example/FruitCommandTest.java GitHub Actions / Java CI / Test Report (17)FruitCommandTest.testCommandPost(EmbeddedServer)
Raw output
Check failure on line 33 in doc-examples/example-java/src/test/java/example/FruitCommandTest.java GitHub Actions / Java CI / Test Report (21)FruitCommandTest.testCommandPost(EmbeddedServer)
Raw output
Check failure on line 33 in doc-examples/example-java/src/test/java/example/FruitCommandTest.java GitHub Actions / Java CI / Test Report (21)FruitCommandTest.testCommandPost(EmbeddedServer)
Raw output
|
||
Object message = ((Map<String, Object>) ((List) embedded.get("errors")).get(0)).get("message"); | ||
|
||
assertEquals("fruitCommand.name: must not be empty", message); | ||
} | ||
} | ||
|
||
@Controller("/fruits") | ||
@Requires(property = "spec.name", value = "FruitCommandTest") | ||
static class FruitCommandController { | ||
|
||
@Post | ||
FruitCommand save(@Valid @Body FruitCommand fruitCommand) { | ||
return fruitCommand; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package example | ||
|
||
import io.micronaut.serde.annotation.Serdeable | ||
import jakarta.validation.constraints.NotEmpty | ||
|
||
@Serdeable // <1> | ||
data class FruitCommand( | ||
@field:NotEmpty val name: String, // <2> | ||
val description: String? = null // <3> | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package example | ||
|
||
import io.micronaut.context.annotation.Property | ||
import io.micronaut.context.annotation.Requires | ||
import io.micronaut.http.HttpRequest | ||
import io.micronaut.http.annotation.Body | ||
import io.micronaut.http.annotation.Controller | ||
import io.micronaut.http.annotation.Post | ||
import io.micronaut.http.client.HttpClient | ||
import io.micronaut.http.client.exceptions.HttpClientResponseException | ||
import io.micronaut.runtime.server.EmbeddedServer | ||
import io.micronaut.test.extensions.junit5.annotation.MicronautTest | ||
import jakarta.inject.Singleton | ||
import org.junit.jupiter.api.Assertions | ||
import org.junit.jupiter.api.Test | ||
import org.junit.jupiter.api.assertThrows | ||
|
||
@MicronautTest | ||
@Property(name = "spec.name", value = "FruitCommandTest") | ||
class FruitCommandTest { | ||
|
||
@Test | ||
fun testCommandPost(embeddedServer: EmbeddedServer) { | ||
embeddedServer.applicationContext.createBean(HttpClient::class.java, embeddedServer.url).use { client -> | ||
val ex = assertThrows<HttpClientResponseException> { | ||
client.toBlocking() | ||
.exchange<FruitCommand, String>( | ||
HttpRequest.POST("/fruits", FruitCommand("", "")) | ||
) | ||
} | ||
val embedded = ex.response.getBody(MutableMap::class.java).get().get("_embedded") as Map<String, Any> | ||
val message = ((embedded["errors"] as List<*>)[0] as Map<String, Any>)["message"] | ||
Assertions.assertEquals("fruitCommand.name: must not be empty", message) | ||
} | ||
} | ||
|
||
@Singleton | ||
@Controller("/fruits") | ||
@Requires(property = "spec.name", value = "FruitCommandTest") | ||
class FruitCommandController { | ||
|
||
@Post | ||
fun save(@Body fruitCommand: FruitCommand): FruitCommand { | ||
return fruitCommand | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package example | ||
|
||
import io.micronaut.serde.annotation.Serdeable | ||
import jakarta.validation.constraints.NotEmpty | ||
|
||
@Serdeable | ||
data class FruitCommand( | ||
@field:NotEmpty val name: String, | ||
val description: String? = null | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package example | ||
|
||
import io.micronaut.context.annotation.Property | ||
import io.micronaut.context.annotation.Requires | ||
import io.micronaut.http.HttpRequest | ||
import io.micronaut.http.annotation.Body | ||
import io.micronaut.http.annotation.Controller | ||
import io.micronaut.http.annotation.Post | ||
import io.micronaut.http.client.HttpClient | ||
import io.micronaut.http.client.exceptions.HttpClientResponseException | ||
import io.micronaut.runtime.server.EmbeddedServer | ||
import io.micronaut.test.extensions.junit5.annotation.MicronautTest | ||
import jakarta.inject.Singleton | ||
import org.junit.jupiter.api.Assertions.assertEquals | ||
import org.junit.jupiter.api.Test | ||
import org.junit.jupiter.api.assertThrows | ||
|
||
@MicronautTest | ||
@Property(name = "spec.name", value = "FruitCommandTest") | ||
class FruitCommandTest { | ||
|
||
@Test | ||
fun testCommandPost(embeddedServer: EmbeddedServer) { | ||
embeddedServer.applicationContext.createBean(HttpClient::class.java, embeddedServer.url).use { client -> | ||
val ex = assertThrows<HttpClientResponseException> { | ||
client.toBlocking() | ||
.exchange<FruitCommand, String>( | ||
HttpRequest.POST("/fruits", FruitCommand("", "")) | ||
) | ||
} | ||
val embedded = ex.response.getBody(MutableMap::class.java).get().get("_embedded") as Map<String, Any> | ||
val message = ((embedded["errors"] as List<*>)[0] as Map<String, Any>)["message"] | ||
assertEquals("fruitCommand.name: must not be empty", message) | ||
} | ||
} | ||
|
||
@Singleton | ||
@Controller("/fruits") | ||
@Requires(property = "spec.name", value = "FruitCommandTest") | ||
class FruitCommandController { | ||
|
||
@Post | ||
fun save(@Body fruitCommand: FruitCommand): FruitCommand { | ||
return fruitCommand | ||
} | ||
} | ||
} |