Search code examples
kotlinreactive-programmingspring-webfluxproject-reactor

Exception in Mono.fromCallable is not resulting in an error


I am trying out kotlin in a home project with Spring webflux and project reactor. I am trying to do a blocking call to the H2 database and I am therefore using the fromCallable method as recommended. To my understanding and experience, fromCallable is supposed to wrap any encountered exception which can then be handled using doOnError, but instead, the error is displayed directly in the console.

fun updateUser(req: ServerRequest): Mono<ServerResponse> =
    req.bodyToMono(UserDto::class.java)
        .flatMap { userDto -> updateUser(userDto) }
        .flatMap { user -> ServerResponse.ok().syncBody(user!!) }
        .doOnError { ServerResponse.notFound().build() }

fun updateUser(userDto: UserDto): Mono<User?> =
    Mono.fromCallable {
        val id = userDto.id.toLong()
        userRepository.findByIdOrNull(id) ?: 
            throw IllegalArgumentException("No user found")
    }.subscribeOn(Schedulers.elastic())

If I ask for an Id that does not exist in my database, I would expect a 404 back. Instead, I get a 500 back from the request and the IllegalArgumentException straight into my console in the IDE. If anyone can tell me why this is, or have any info about this, it would be greatly appreciated!


Solution

  • doOnError adds behavior if a mono terminates with an error. In other words, it adds a side effect but doesn't change the stream. Replace doOnError with onErrorResume. onErrorResume it exactly what you need, it subscribes to a fallback publisher if any error occurs.

    fun updateUser(req: ServerRequest): Mono<ServerResponse> =
        req.bodyToMono(UserDto::class.java)
            .flatMap { userDto -> updateUser(userDto) }
            .flatMap { user -> ServerResponse.ok().syncBody(user!!) }
            .onErrorResume { ServerResponse.notFound().build() }       // fallback publisher
            .doOnError { println("Failed to perform an update: $it") } // side effect