I'm using Retrofit to return rxjava Observable's for my async network calls.
I find myself repeating the following invocation:
someApiCall().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
Seems like I'm always subscribing on the IO thread and observing on the Android main thread. This seems to be the best practice that all the resources I found advocate. Perhaps other than long-running computations, I don't quite understand when we would want to deviate from this pattern.
Is there a way to remove this boilerplate by defaulting the subscribeOn and observeOn threads?
Is this a use case for rxjava plugins? (I can't find many examples of their use.)
Can I set the default threads at the network boundary by messing with the retrofit executors?
For Observable responses, Retrofit currently sets the subscribeOn as the HTTP executor of the RestAdapter (either provided or the default). This was done to shim RxJava support into the existing behavior.
The plan for 2.0 is to provide the ability to set defaults for both subscribeOn and observeOn explicitly (whether it be both, only one, or neither).
A reason you wouldn't want always want observation on the main thread is if you needed to chain multiple API calls together, for example.
The Change Log of Retrofit Version 2.0.0-beta2 (2015-09-28) shows subscribeOn() is required for running in the background.
Fix: Observable and Single-based execution of requests now behave synchronously (and thus requires subscribeOn() for running in the background).
Yes, it's possible to remove both calls.
Here is the retrofit adapter class that automatically schedules both subscribeOn and observedOn to remove the need for the boilerplate calls in each invocation:
public class RxThreadingCallAdapterFactory extends CallAdapter.Factory {
private final RxJava2CallAdapterFactory original;
private RxThreadingCallAdapterFactory() {
// Always call on background thread
original = RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io());
}
public static CallAdapter.Factory create() {
return new RxThreadingCallAdapterFactory();
}
#Override
public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
return new RxCallAdapterWrapper(original.get(returnType, annotations, retrofit));
}
private static class RxCallAdapterWrapper implements CallAdapter<Observable<?>> {
private final CallAdapter<?> wrapped;
public RxCallAdapterWrapper(CallAdapter<?> wrapped) {
this.wrapped = wrapped;
}
#Override
public Type responseType() {
return wrapped.responseType();
}
#Override
public <R> Observable<?> adapt(Call<R> call) {
Observable observable = (Observable) wrapped.adapt(call);
// Always handle result on main thread
return observable.observeOn(AndroidSchedulers.mainThread());
}
}
}
Then use this adapter when configuring retrofit:
Retrofit.Builder()
.baseUrl(...)
.addCallAdapterFactory(RxThreadingCallAdapterFactory.create())
I wrote this blog post that goes into a lot of detail on exactly what's happening here.
This will remove both calls, which I consider boilerplate. I consider Jake's scenario of chaining together background calls to not really apply, because in this case I would do retrofit synchronous calls and not use schedulers at all.
it is not the full answer to what you are looking for, but this at least removes the burden of righting subscribeOn(Schedulers.io())
retrofit = new Retrofit
.Builder()
.baseUrl(app.getUrlBase())
.client(httpClient)
.addCallAdapterFactory(
RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()) // <-- default subscribeOn()
)
.addConverterFactory(jsonFactory)
.build();
Related
I don't want to perform a blocking operation.
Caused by: java.lang.IllegalStateException: You have attempted to perform a blocking operation on a IO thread. This is not allowed, as blocking the IO thread will cause major performance issues with your application. If you want to perform blocking EntityManager operations make sure you are doing it from a worker thread.
Anyone know how to fix this problem?
I only have simple operations. a single findAll request that returns 10 rows. I put Tansactional NEVER
and I still have the problem.
I'm using panache with a simple entity.
#GET
#Path("/type")
#Produces(MediaType.APPLICATION_JSON)
#Transactional(Transactional.TxType.NEVER)
public Response get() {
return AlertType.listAll();
}
public class AlerteType extends PanacheEntityBase
{
#Column(name="ATY_ACTIVE")
private String active;
#Column(name="ATY_ID")
#Id
private Long oraId;
#Column(name="ATY_TYPE")
private String type;
}
thank
If you want to keep using non-reactive code, you can use #Blocking annotation on the method get(). It will offload the computation on a worker thread (instead of one IO thread).
Quarkus is really picky with IO thread, you cannot block them. And if you have something like a database call (or any remote call), that is blocking. So you cannot do it in an IO thread.
More info:
https://quarkus.io/guides/getting-started-reactive
https://quarkus.io/blog/resteasy-reactive-faq/
"Controller" methods (request / route / path handlers, or whatever you call it) is executed on IO thread and not supposed to do any time consuming tasks such as database querying.
If you're not using reactive database client, try wrap them in side a "Service" class.
#ApplicationScoped
public class AlertService {
private final AlertType alertType;
#Inject
public AlertService(AlertType alertType) {
this.alertType = alertType;
}
public List<Alert> listAll() {
return this.alertType.listAll();
}
}
thank you but I already had the call in a service.
I found a solution with mutiny
#GET
#Path("type")
#Produces(MediaType.APPLICATION_JSON)
public Uni<Response> get() {
return Uni.createFrom().item(alertTypeService.findAll().get())
.onItem().transform(data -> Response.ok(data))
.onFailure().recoverWithItem(err -> Response.status(600, err.getMessage()))
.onItem().transform(ResponseBuilder::build)
.emitOn(Infrastructure.getDefaultExecutor())
}
Where alertTypeService.findAll() return a supplier
#Transactional(Transactional.TxType.NEVER)
public Supplier<Set<AlerteTypeDTO>> findAll() {
return () -> alerteTypeDAO.streamAll()
.map(AlertTypeDTOMapper::mapToDTO)
.collect(Collectors.toSet());
}
I don't know if this is the right solution
but it works.
This way the service provides a supplier which will be invoked by the correct thread.
At least that's how I understood it.
I'm currently checking out the following guide: https://developer.android.com/topic/libraries/architecture/guide.html
The networkBoundResource class:
// ResultType: Type for the Resource data
// RequestType: Type for the API response
public abstract class NetworkBoundResource<ResultType, RequestType> {
// Called to save the result of the API response into the database
#WorkerThread
protected abstract void saveCallResult(#NonNull RequestType item);
// Called with the data in the database to decide whether it should be
// fetched from the network.
#MainThread
protected abstract boolean shouldFetch(#Nullable ResultType data);
// Called to get the cached data from the database
#NonNull #MainThread
protected abstract LiveData<ResultType> loadFromDb();
// Called to create the API call.
#NonNull #MainThread
protected abstract LiveData<ApiResponse<RequestType>> createCall();
// Called when the fetch fails. The child class may want to reset components
// like rate limiter.
#MainThread
protected void onFetchFailed() {
}
// returns a LiveData that represents the resource
public final LiveData<Resource<ResultType>> getAsLiveData() {
return result;
}
}
I'm a bit confused here about the use of threads.
Why is #MainThread applied here for networkIO?
Also, for saving into the db, #WorkerThread is applied, whereas #MainThread for retrieving results.
Is it bad practise to use a worker thread by default for NetworkIO and local db interaction?
I'm also checking out the following demo (GithubBrowserSample): https://github.com/googlesamples/android-architecture-components
This confuses me from a threading point of view.
The demo uses executors framework, and defines a fixed pool with 3 threads for networkIO, however in the demo only a worker task is defined for one call, i.e. the FetchNextSearchPageTask. All other network requests seem to be executed on the main thread.
Can someone clarify the rationale?
It seems you have a few misconceptions.
Generally it is never OK to call network from the Main (UI) thread but unless you have a lot of data it might be OK to fetch data from DB in the Main thread. And this is what Google example does.
1.
The demo uses executors framework, and defines a fixed pool with 3 threads for networkIO, however in the demo only a worker task is defined for one call, i.e. the FetchNextSearchPageTask.
First of all, since Java 8 you can create simple implementation of some interfaces (so called "functional interfaces") using lambda syntax. This is what happens in the NetworkBoundResource:
appExecutors.diskIO().execute(() -> {
saveCallResult(processResponse(response));
appExecutors.mainThread().execute(() ->
// we specially request a new live data,
// otherwise we will get immediately last cached value,
// which may not be updated with latest results received from network.
result.addSource(loadFromDb(),
newData -> result.setValue(Resource.success(newData)))
);
});
at first task (processResponse and saveCallResult) is scheduled on a thread provided by the diskIO Executor and then from that thread the rest of the work is scheduled back to the Main thread.
2.
Why is #MainThread applied here for networkIO?
and
All other network requests seem to be executed on the main thread.
This is not so. Only result wrapper i.e. LiveData<ApiResponse<RequestType>> is created on the main thread. The network request is done on a different thread. This is not easy to see because Retrofit library is used to do all the network-related heavy lifting and it nicely hides such implementation details. Still, if you look at the LiveDataCallAdapter that wraps Retrofit into a LiveData, you can see that Call.enqueue is used which is actually an asynchronous call (scheduled internally by Retrofit).
Actually if not for "pagination" feature, the example would not need networkIO Executor at all. "Pagination" is a complicated feature and thus it is implemented using explicit FetchNextSearchPageTask and this is a place where I think Google example is done not very well: FetchNextSearchPageTask doesn't re-use request parsing logic (i.e. processResponse) from RepoRepository but just assumes that it is trivial (which it is now, but who knows about the future...). Also there is no scheduling of the merging job onto the diskIO Executor which is also inconsistent with the rest of the response processing.
I'm currently building a small Social Media style App which leverages RxJava 2 and Firebase. I'm using MVP style architecture, and I've abstracted out my AuthService with an interface called AuthSource.
For simplicity's sake, I'll work with a Single method in my Service:
public class FirebaseAuthService implements AuthSource {
private FirebaseAuth auth;
private FirebaseAuth.AuthStateListener listener;
//initialization code
#Override
public Maybe<User> getUser() {
return Maybe.create(new MaybeOnSubscribe<User>() {
#Override
public void subscribe(final MaybeEmitter<User> e) throws Exception {
if (auth == null) {
auth = FirebaseAuth.getInstance();
}
if (listener != null) {
auth.removeAuthStateListener(listener);
}
listener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
auth.removeAuthStateListener(listener);
if (firebaseUser != null) {
User user = new User(
firebaseUser.getDisplayName(),
firebaseUser.getEmail());
user.setUserId(firebaseUser.getUid());
Uri photoUrl = firebaseUser.getPhotoUrl();
if (photoUrl != null){
user.setProfilePhotoUrl(photoUrl.toString());
}
e.onSuccess(user);
} else {
e.onComplete();
}
}
};
auth.addAuthStateListener(listener);
}
}
);
}
}
interface AuthSource {
Maybe<User> getUser();
//Other methods etc.
}
Finally, I'll show my Presenter method which handles the call:
//from with a Presenter:
#Override
private void getUserData() {
disposableSubscriptions.add(
auth.getUser().subscribeOn(schedulerProvider.io())
.observeOn(schedulerProvider.ui())
.subscribeWith(
new DisposableMaybeObserver<User>() {
#Override
public void onError(Throwable e) {
view.makeToast(R.string.error_retrieving_data);
view.startDispatchActivity();
}
#Override
public void onComplete() {
}
#Override
public void onSuccess(User user) {
ProfilePagePresenter.this.currentUser = user;
view.setName(user.getName());
view.setEmail(user.getEmail());
if (user.getProfilePhotoUrl().equals("")) {
view.setDefaultProfilePhoto();
} else {
view.setProfilePhotoURI(user.getProfilePhotoUrl());
}
getUserProfileFromDatabase();
}
}
)
);
}
I realize the topic of the question is a bit general, so I'll try to narrow things down from here. The code I've posted above works insofar as I'm succesfully getting Data from Firebase's API using Create(). The problem is, I'm quite new to using RxJava 2, and I'm not certain what's going on under the hood here for garbage collection and memory leaks. I chose to use Observable.create() as per the RxJava 2 Docs:
"Provides an API (via a cold Observable) that bridges the reactive world with the callback-style world."
RxJava 2 Docs
Finally, the only proactive thing I'm doing at the moment to dispose of these Observables, is to call CompositeDisposable.clear() in my Presenter when events take the user to a new Activity.
Questions:
-Is it safe to assume that simply calling CompositeDisposable.clear() when the Presenter finishes, will handle my Garbage collection? (assuming I haven't created memory leaks in the rest of the code).
-If my understanding is correct, create() is a better option to use than fromCallable() in this case, as fromCallable() should be used for Synchronous events (i.e. not something like Firebase API callbacks)?
-Is it really as simple as just throwing my Asynchronous callbacks in Observable.create()? I'm terrified at how easy that is to do...
Is it safe to assume that simply calling CompositeDisposable.clear()
when the Presenter finishes, will handle my Garbage collection?
(assuming I haven't created memory leaks in the rest of the code).
It's a little trickier than this. Non-disposed Observable won't create memory leak if everything referenced by the Observable belong to the Activity scope. Both the producer and the consumer will be garbage collected alongside Activity. Memory leak may occur if you referenced resources that will survive the Activity, a provider instantiated at Application level for example. So if you want to use CompositeDisposable.clear() make sure to implement emitter.setCancellable() inside Observable.create() to dispose those leaky resources.
If my understanding is correct, create() is a better option to use
than fromCallable() in this case, as fromCallable() should be used for
Synchronous events (i.e. not something like Firebase API callbacks)?
create() use to be named fromAsync(). Use fromCallable() to wrap a synchronous method call, create() when wrapping callback code.
Is it really as simple as just throwing my Asynchronous callbacks in
Observable.create()? I'm terrified at how easy that is to do...
It is as easy ... if you take care of those pesky references outside of scope as mentioned at the first point.
Usually on Android, a memory leak involve the Context, which is big. Be sure to test your code. leakcanary is a great help for this matter.
Last, you could avoid doing the wrapping yourself by using an existing Firebase RxJava binding. Or take inspiration from them:
https://github.com/kunny/RxFirebase
https://github.com/ashdavies/rx-firebase
https://github.com/DariusL/RxFirebaseAndroid
https://github.com/ezhome/Android-RxFirebase
https://github.com/nmoskalenko/RxFirebase
https://github.com/VictorAlbertos/RxFcm
Calling clear will detach the subscriber - the code that reacts to the emitted events, from the Observable, and as a result the subscriber which is enclosed by the presenter/activity and has hard reference to it, will no longer be held by the observer and lived longer than the presenter/activity lifecycle.
But, beware, you still can cause leaks if your Observable itself contains references to your presenter/activity.
In either cases, leak will occur when you reference your activity/presenter by static or other object that lives in longer (for instance Application) context than your activity/presenter.
Indeed, create() method is the correct way to create Observable from async method (BTW, in RxJava1, there was a different obsolete way that called also create, but it was changed in RxJava2, so there will be no way of creating Observable wrongly, but that's a different story)
Well, you still need to make sure you obey to the Observable contract,
make sure that there will be terminal event (either onComplete/onError),
there will be no onNext after terminal event (onCompleted/onError), and backpressure (which is enforced with Flowable Observable)
I have a webapp in which I have to return the results from a mongodb find() to the front-end from my java back-end.
I am using the Async Java driver, and the only way I think I have to return the results from mongo is something like this:
public String getDocuments(){
...
collection.find(query).map(Document::toJson)
.into(new HashSet<String>(), new SingleResultCallback<HashSet<String>>() {
#Override
public void onResult(HashSet<String> strings, Throwable throwable) {
// here I have to get all the Json Documents in the set,
// make a whole json string and wake the main thread
}
});
// here I have to put the main thread to wait until I get the data in
// the onResult() method so I can return the string back to the front-end
...
return jsonString;
}
Is this assumption right or thereĀ“s another way to do it?
Asynchronous APIs (any API based on callbacks, not necessarily MongoDB) can be a true blessing for multithreaded applications. But to really benefit from them, you need to design your whole application architecture in an asynchronous fashion. This is not always feasible, especially when it is supposed to fit into a given framework which isn't built on callbacks.
So sometimes (like in your case) you just want to use an asynchronous API in a synchronous fashion. In that case, you can use the class CompletableFuture.
This class provides (among others) two methods <T> get() and complete(<T> value). The method get will block until complete is called to provide the return value (should complete get called before get, get returns immediately with the provided value).
public String getDocuments(){
...
CompletableFuture<String> result = new CompletableFuture<>(); // <-- create an empty, uncompleted Future
collection.find(query).map(Document::toJson)
.into(new HashSet<String>(), new SingleResultCallback<HashSet<String>>() {
#Override
public void onResult(HashSet<String> strings, Throwable throwable) {
// here I have to get all the Json Documents in the set and
// make a whole json string
result.complete(wholeJsonString); // <--resolves the future
}
});
return result.get(); // <-- blocks until result.complete is called
}
The the get()-method of CompletableFuture also has an alternative overload with a timeout parameter. I recommend using this to prevent your program from accumulating hanging threads when the callback is not called for whatever reason. It will also be a good idea to implement your whole callback in a try { block and do the result.complete in the finally { block to make sure the result always gets resolved, even when there is an unexpected error during your callback.
Yes, you're right.
That's the correct behaviour of Mongo async driver (see MongoIterable.into).
However, Why don't you use sync driver in this situation? Is there any reason to use async method?
I have a layered architecture in a Java web application. The UI layer is just Java, services are typed Akka actors and external service calls (WS, DB etc.) are wrapped in Hystrix commands.
THe UI calls the service and the service returns an Akka future. It's an Akka future because I want to make UI coding simpler with the onComplete and onFailure callbacks that Akka futures provide. The service then creates the future that does some mapping etc. and wraps a call to a HystrixCommand that returns a Java future.
So in pseudocode:
UI
AkkaFuture future = service.getSomeData();
Service
public AkkaFuture getSomeData() {
return future {
JavaFuture future = new HystrixCommand(mapSomeData()).queue()
//what to do here, currently just return future.get()
}
}
The problem is that I would like to free up the thread the service actor is using and just tie up the threads that Hystrix uses. But the java future prevents that because I have to block on it's completion. The only option I can think of (which I'm not sure I like) is to poll the Java future(s) constantly and complete the Akka future when the Java future finishes.
Note: the question isn't really related to Hystrix per se, but I decided to mention it if somebody comes up with a solution specifically related to Hystrix.
I'm marking the answer by #Hbf as a solution, since I ended up doing an Akka poller as explained in How do I wrap a java.util.concurrent.Future in an Akka Future?. For reference I also tried:
Creating a HystrixCommandExcutionHook and extending HystrixCommand to allow callbacks. That didn't work because the hook wasn't called at the right time.
Using Guavas listenable future by having a decorated executor create the futures inside Hystrix and then casting the futures from the commands. Doesn't work because Hystrix uses a ThreadPoolExecutor which can't be decorated.
EDIT: I'm adding the Akka poller code below, since the original answer was in Scala and it hangs if the Java future doesn't cancel nicely. The solution below always walks away from threads after a timeout.
protected Future wrapJavaFutureInAkkaFuture(final java.util.concurrent.Future javaFuture, final Option maybeTimeout, final ActorSystem actorSystem) {
final Promise promise = Futures.promise();
if (maybeTimeout.isDefined()) {
pollJavaFutureUntilDoneOrCancelled(javaFuture, promise, Option.option(maybeTimeout.get().fromNow()), actorSystem);
} else {
pollJavaFutureUntilDoneOrCancelled(javaFuture, promise, Option. none(), actorSystem);
}
return promise.future();
}
protected void pollJavaFutureUntilDoneOrCancelled(final java.util.concurrent.Future javaFuture, final Promise promise, final Option maybeTimeout, final ActorSystem actorSystem) {
if (maybeTimeout.isDefined() && maybeTimeout.get().isOverdue()) {
// on timeouts, try to cancel the Java future and simply walk away
javaFuture.cancel(true);
promise.failure(new ExecutionException(new TimeoutException("Future timed out after " + maybeTimeout.get())));
} else if (javaFuture.isDone()) {
try {
promise.success(javaFuture.get());
} catch (final Exception e) {
promise.failure(e);
}
} else {
actorSystem.scheduler().scheduleOnce(Duration.create(50, TimeUnit.MILLISECONDS), new Runnable() {
#Override
public void run() {
pollJavaFutureUntilDoneOrCancelled(javaFuture, promise, maybeTimeout, actorSystem);
}
}, actorSystem.dispatcher());
}
}
Java futures are known to be inferior in design compared to something like Scala futures. Take a look at the discussion "How do I wrap a java.util.concurrent.Future in an Akka Future", for example.
But: Maybe, instead of polling (as suggested in the above discussion), Hystrix offers some kind of onComplete callback? I do not know the library at all but stumbled upon an onComplete in the Hystrix API. Maybe it helps?
As of Hystrix 1.3 it now also supports true non-blocking callbacks and that will fit much better into Akka/Scala Future behavior that is non-blocking and composable: https://github.com/Netflix/Hystrix/wiki/How-To-Use#wiki-Reactive-Execution