Skip to content

stevenlmcgraw/coroutine-r2dbc-null-value

Repository files navigation

APP SETUP

A Kotlin application uses micronaut-data-r2dbc with a Postgresql database.

The application uses Netty/Reactor and Kotlin coroutines (suspend functions).

An entity is defined using @MappedEntity/@MappedProperty/etcetera io.micronaut.data.annotation.* annotations.

A @R2dbcRepository abstract class is defined for the entity that extends io.micronaut.data.repository.kotlin.CoroutineCrudRepository.

EXPECTATION

A query is intended to fetch the value of a non-nullable column.

If a record exists for the given identifier then the value of the column is returned as expected from the repository method.

If a record does not exist for the given identifier then null is returned from the repository method.

Example in this project

Product

  • Product.id -> val id: String, column name id
  • Product.provider -> val provider: String, column name provider

Repository Method

  • abstract suspend fun getProviderById(@Id id: String): String?

OBSERVED BEHAVIOR

Rather than returning null when a record does not exist for the given identifier, the non-null string "NullValue[]" is returned by the repository method.

This subverts any null checks like the Kotlin elvis operator (?:), leading to unexpected behavior in the application.

The NullValue record class was introduced in this commit.

Older versions of micronaut-data-r2dbc return null as expected.


REPRODUCTION STEPS

  • ./gradlew clean test
  • Kotest StringSpec test named "'::getProviderOrFallback' returns supplied fallback value when record not present for 'id'" {} fails
  • See logs for details (values captured in logger and Kotest matcher output)

About

example for micronaut-data-r2dbc "NullValue[]"

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages