How to handle a multiple singles? - rx-java2

I'm writing messenger server on grpc with rxjava2 stubs, and I stuck on combining my singles.
I'm have tried some sort of
val user:Single<User> = getUser()
val conversation:Single<Conversation> = getConversation(user.blockingGet())
return conversation.map{
someMethod(user.blockingGet(), conversation.it())
it
}
It looks so unbeauty then all of the examples, so is there a way to combine all of this singles to one line?

First a small comment, usually you don't want to use blockingGet. Instead you use other combinators to compose your solution and in the end you use subscribe to evaluate it.
I'm assuming you want to combine multiple calls that return a Single where the result of the next call depends on the previous.
The combinator you are looking for is flatMap.
val user: Single<User> = getUser()
val singleOfSomething: Single<Conversation> = user.flatMap { user->
getConversation(user).flatMap {conversation ->
someMethod(user, conversation)
}
}
here the return type would be Single of whatever someMethod returns.
You would use subscribe to get that value out when you need it.

Related

Array of observables where the output of each is the input of the next

I'm trying to use RxSwift to execute actions on multiple data sources. However, I have no idea how to accomplish the following.
I have an array of observabless where the output of each, should be the input of the next. So, I want to do something like, get the first observable, wait for the result and pass it to the next, all the way to the end of the array and return one final value.
Is that possible? Thanks in advance.
*** Update: Ok, I'll be more specific as requested.
The 'observables' I'm using in the array, are custom. I use a function that returns Observable.create { ... }. Inside the closure, I run an asynchronous operation that transforms the value and then send the result to the observer before completing. That resulting value, must pass to the next observable, and so on to the last observable in the array to get a final value.
The observables may send multiple values, but they must pass from one observable to the next like an assembly line.
It is difficult to know exactly what you are asking for, since Observables do not exactly have inputs but I think this is a common problem.
You may be looking for a combination of the concat or reduce operators, which allow you to accumulate data from the values emitted from an Observable. See ReactiveX's documentation for Mathematical and Aggregate Operators.
Hopefully this can get you started:
// "I have an array of observables..."
let one = Observable.deferred { Observable.just(1) }
let two = Observable.deferred { Observable.just(2) }
let observables = [one, two]
// "the output of each, should be the input of the next"
// this is problematic, because observables do not strictly have inputs.
let resultsFromEach = Observable.concat(observables)
resultsFromEach
.reduce(0) { result, next in
result + 1
}
.debug("result")
.subscribe()

can i conditionally "merge" a Single with an Observable?

i'm a RxJava newcomer, and i'm having some trouble wrapping my head around how to do the following.
i'm using Retrofit to invoke a network request that returns me a Single<Foo>, which is the type i ultimately want to consume via my Subscriber instance (call it SingleFooSubscriber)
Foo has an internal property items typed as List<String>.
if Foo.items is not empty, i would like to invoke separate, concurrent network requests for each of its values. (the actual results of these requests are inconsequential for SingleFooSubscriber as the results will be cached externally).
SingleFooSubscriber.onComplete() should be invoked only when Foo and all Foo.items have been fetched.
fetchFooCall
.subscribeOn(Schedulers.io())
// Approach #1...
// the idea here would be to "merge" the results of both streams into a single
// reactive type, but i'm not sure how this would work given that the item emissions
// could be far greater than one. using zip here i don't think it would every
// complete.
.flatMap { foo ->
if(foo.items.isNotEmpty()) {
Observable.zip(
Observable.fromIterable(foo.items),
Observable.just(foo),
{ source1, source2 ->
// hmmmm...
}
).toSingle()
} else {
Single.just(foo)
}
}
// ...or Approach #2...
// i think this would result in the streams for Foo and items being handled sequentially,
// which is not really ideal because
// 1) i think it would entail nested streams (i get the feeling i should be using flatMap
// instead)
// 2) and i'm not sure SingleFooSubscriber.onComplete() would depend on the completion of
// the stream for items
.doOnSuccess { data ->
if(data.items.isNotEmpty()) {
// hmmmm...
}
}
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ data -> /* onSuccess() */ },
{ error -> /* onError() */ }
)
any thoughts on how to approach this would be greatly appreciated!
bonus points: in trying to come up with a solution to this, i've begun to question the decision to use the Single reactive type vs the Observable reactive type. most (all, except this one Foo.items case?) of my streams actually revolve around consuming a single instance of something, so i leaned toward Single to represent my streams as i thought it would add some semantic clarity around the code. anybody have any general guidance around when to use one vs the other?
You need to nest flatMaps and then convert back to Single:
retrofit.getMainObject()
.flatMap(v ->
Flowable.fromIterable(v.items)
.flatMap(w ->
retrofit.getItem(w.id).doOnNext(x -> w.property = x)
)
.ignoreElements()
.toSingle(v)
)

Play Framework Search Bar

I'm trying to make a search bar with only one variable - the search input. I'm sure there's a fairly simple way to do this, but everything that I've found about getting input from the DOM (the views file) has been about using a Form and getting multiple variables. Is there a simpler way to do this if it's just a single variable?
I have a function in my Applications
def singleElement = Action { implicit request =>
val databaseSupport = new InteractWithDatabase(comm, db)
val put = Future {
while (true) {
val data = databaseSupport.getFromDatabase()
if (data.nonEmpty) {
comm.communicator ! data.head
}
}
}
Ok(views.html.singleElement)
}
I want to take some input from the user on the page singleElement and pass it into getFromDatabase which calls a MySQL query. How do I do this?
You can use restful and do something like this
routs file
GET /content/search/:search controllers.ContentController.search(search:String)
and in controller:
public Result search(String saerch) {}

Capture a return value for logging and then return the value in Scala

What is the most 'scala-ic' way to capture a value (possibly one that is not idempotent) for logging and returning the same value.
I can think of 'return' statement the only way to do it, but apparently using 'return' should be avoided in scala .
Use case:
def myfunc(argument) : ReturnType{
val response:ReturnType = dependency()
// dependency() is not idemptotent
// so calling more than once will have side-effects
logger.debug(response.member1 , response.member2)
return response
}
Is there a way to achieve this without using a 'return' keyword.
I am a newbie to scala so some (or most) of what I said could be wrong, and would be happy to be corrected.
Just reifying #Shadowlands answer.
def myfunc(argument: ArgType): ReturnType {
val response = dependency()
logger.debug(response.member1, response.member2)
response
}

How to check for null in a single statement in scala?

In my scala code:
QueueManager.add(getObject)
where getObject is a method that returns an object of type QueueObject.
def getObject : QueuObject = {
val response = //some response
return response
}
Is there a way I can check for the response being null, while adding the QueueObject? I know I can do this:
if (getObject != null)
QueueManager.add(getObject)
But I do not wish to add a level of indentation. Is there an operator that does that inline?
Thanks.
Try to avoid using null in Scala. It's really there only for interoperability with Java. In Scala, use Option for things that might be empty. If you're calling a Java API method that might return null, wrap it in an Option immediately.
def getObject : Option[QueueObject] = {
// Wrap the Java result in an Option (this will become a Some or a None)
Option(someJavaObject.getResponse)
}
Note: You don't need to put it in a val or use an explicit
return statement in Scala; the result will be the value of
the last expression in the block (in fact, since there's only one statement, you don't even need a block).
def getObject : Option[QueueObject] = Option(someJavaObject.getResponse)
Besides what the others have already shown (for example calling foreach on the Option, which might be slightly confusing), you could also call map on it (and ignore the result of the map operation if you don't need it):
getObject map QueueManager.add
This will do nothing if the Option is a None, and call QueueManager.add if it is a Some.
I find using a regular if however clearer and simpler than using any of these "tricks" just to avoid an indentation level. You could also just write it on one line:
if (getObject.isDefined) QueueManager.add(getObject.get)
or, if you want to deal with null instead of using Option:
if (getObject != null) QueueManager.add(getObject)
edit - Ben is right, be careful to not call getObject more than once if it has side-effects; better write it like this:
val result = getObject
if (result.isDefined) QueueManager.add(result.get)
or:
val result = getObject
if (result != null) QueueManager.add(result)
Option(getObject) foreach (QueueManager add)
If it instead returned Option[QueueObject] you could use a construct like getObject.foreach { QueueManager.add }. You can wrap it right inline with Option(getObject).foreach ... because Option[QueueObject](null) is None.
Although I'm sure #Ben Jackson's asnwer with Option(getObject).foreach is the preferred way of doing it, I like to use an AnyRef pimp that allows me to write:
getObject ifNotNull ( QueueManager.add(_) )
I find it reads better.
And, in a more general way, I sometimes write
val returnVal = getObject ifNotNull { obj =>
returnSomethingFrom(obj)
} otherwise {
returnSomethingElse
}
... replacing ifNotNull with ifSome if I'm dealing with an Option. I find it clearer than first wrapping in an option and then pattern-matching it.
(For the implementation, see Implementing ifTrue, ifFalse, ifSome, ifNone, etc. in Scala to avoid if(...) and simple pattern matching and the Otherwise0/Otherwise1 classes.)