billydh
billydh

Reputation: 1035

How to place a conditional check inside springboot project reactor Mono stream (written in Kotlin)?

Pretty new to project reactor here, I am struggling to put a conditional check inside my Mono stream. This part of my application is receiving an object from Kafka. Let's say the object is like this.

data class SomeEvent(val id: String, val type: String)

I have a function that handles this object like this.

fun process(someEvent: SomeEvent): Mono<String> {
  val id = someEvent.id
  val checkCondition = someEvent.type == "thisType"

  return repoOne.getItem(id)
    .map {item ->
      // WHAT DO I DO HERE TO PUT A CONDITIONAL CHECK
      createEntryForItem(item)
    }
    .flatMap {entry ->
      apiService.sendEntry(entry)
    }
    .flatMap {
      it.bodyToMono(String::class.java)
    }
    .flatMap {body ->
      Mono.just(body)
    }
}

So, what I want to do is check whether checkCondition is true and if it is, I want to call a function repoTwo.getDetails(id) that returns a Mono<Details>.

createEntryForItem returns an object of type Entry

apiService.sendEntry(entry) returns a Mono<ClientResponse>

It'd be something like this (in my mind).

fun process(someEvent: SomeEvent): Mono<String> {
  val id = someEvent.id
  val checkCondition = someEvent.type == "thisType"

  return repoOne.getItem(id)
    .map {item ->
      if (checkCondition) {
        repoTwo.getDetails(id).map {details ->
          createEntryForItem(item, details)
        }
      } else {
        createEntryForItem(item)
      }          
    }
    .flatMap {entry ->
      apiService.sendEntry(entry)
    }
    .flatMap {
      it.bodyToMono(String::class.java)
    }
    .flatMap {body ->
      Mono.just(body)
    }
}

But, obviously, this does not work because the expression inside the if statement is cast to Any.

How should I write it to achieve what I want to achieve?

UPDATED: The location of where I like to have the conditional check.

Upvotes: 1

Views: 2443

Answers (2)

adrianbukros
adrianbukros

Reputation: 336

You should use flatMap() and not map() after getItem().

return repoOne.getItem(id)
    .flatMap {item ->
      if (checkCondition) {
        repoTwo.getDetails(id).map {details ->
          createEntryForItem(item, details)
        }
      } else {
        Mono.just(createEntryForItem(item))
      }          
    }

In a map{} you can transform the value. Because you want to call getDetails() (which returns a reactive type and not a value) to do that you have to use flatMap{}. And that's why you need to wrap your item in a Mono by calling Mono.just(createEntryForItem(item)) on the else branch.

Upvotes: 1

Tatu Lahtela
Tatu Lahtela

Reputation: 4554

Just split it to another function. Your code will be cleaner too.

repoOne.getItem(id)
    .map { createEntry(it, checkCondition) }.
    .flatMap.....


private fun createEntry(item, checkCondition): Item {
  return if (checkCondition) {
      repoTwo.getDetails(id).map { createEntryForItem(item, it) }        
  } else {
      createEntryForItem(item)
  }
}

Upvotes: 0

Related Questions