So I'm completely new to rx-java/rx-kotlin and haven't heard about it until I where to write a HTTP filter in Micronaut (https://docs.micronaut.io/latest/guide/index.html#filters) which caught me off guard since I've only done regular JAX-RS filters.
So after doing some trial-and-error I came up with this.
return Flowable.fromPublisher(remoteClient.getPermissions(userId))
.subscribeOn(Schedulers.io())
.onErrorReturn { e ->
logger.error("Error when fetching users from remote service", e)
emptyList()
}
.switchMap { permissions ->
if (permissions.contains(somePermission)) {
chain.proceed(request)
} else {
val response = HttpResponseFactory.INSTANCE.status(
HttpStatus.FORBIDDEN,
"No user found"
)
Flowable.just(response)
}
}
Code is rewritten but point still stands. There's some room for improvement here.
What I'd like to do is to improve the exception handling and return a 500 in the case an exception is thrown (like if the remote service called by remoteClient
isn't reachable. How can I accomplish this? I haven't got anything else to work other than the solution above to return an empty list for the next observer.
You can move the onErrorReturn
operator after the switchMap
operator. If getPermissions
emits an error, execution will skip your switchMap
, and pick up inside of onErrorReturn
:
return Flowable.fromPublisher(remoteClient.getPermissions(userId))
.subscribeOn(Schedulers.io())
.switchMap { permissions ->
if (permissions.contains(somePermission)) {
chain.proceed(request)
} else {
val response = HttpResponseFactory.INSTANCE.status(
HttpStatus.FORBIDDEN,
"No user found"
)
Flowable.just(response)
}
}
.onErrorReturn { e ->
logger.error("Error when fetching users from remote service", e)
val response = // whatever
return response
}
Note that an exception occurring inside of switchMap
will also result in onErrorReturn
getting executed. So you either want to examine the Exception that is passed into onErrorReturn
to decide what response to use, or embed an onErrorReturn
inside of switchMap
, chained to the chain.proceed(request)
call, to prevent it from emitting an exception downstream.