How to make linear/more readable Java code with background/asynctask - java

At the moment I have something like;
public class SomeActivity {
void onCreate() {
doSomething();
if (weNeedToDoSomeAsncTask()) {
new SomeAsyncTask(afterSomeAsyncTask).execute();
} else {
new DifferentAsyncTask(afterAnotherAsyncTask).execute();
}
}
PostExecute afterSomeAsyncTask = new PostExecute() {
void Callback(String response) {
doSomethingElse(response);
new DifferentAsyncTask(afterAnotherAsyncTask).execute();
}
}
}
This doesn't look too bad on the face of it, but I have hugely simplified the code and you can imagine how complex it becomes when you have more than a few calls going on and some branching starts to happen.
To help with context, the actual use case is normally something like;
use an sdk to get some device/user information
use the returned information to authenticate with a web service
send some logging info to the web service
get some data from the web service
get some other data from the web service
use that data to generate the UI
I would prefer my code to look a bit more like;
public class SomeActivity {
void onCreate() {
doSomething();
if (weNeedToDoSomeAsncTask()) {
new SomeAsyncTask().execute();
doSomethingElse(response);
}
new DifferentAsyncTask().execute();
afterAnotherAsyncTask();
}
}
I have tried used .get() in the past and had issues but never got to the bottom of why (potentially I was trying to call one AsyncTask inside another, which I've read is a no go- but it was a long time ago so can't be sure). Whilst I realise .get somewhat defeats the object of AsyncTask, I am only using it because Java forces me to (for network communication etc). My application is relying on the result to continue and can't do anything else till it returns anyway.
Should I try the .get() technique again? Or is it a really bad idea?
Should I just suck it up and realise the code is harder to read and I will need to jump to the callback methods to try and understand the code flow?
Or is there a different option?
I have also just learnt of Needle which looks like quite a nice library https://zsoltsafrany.github.io/needle/ and I think I could do more like;
NetworkService networkService = new NetworkService();
Needle.onBackgroundThread().serially().execute(networkService);
String result = doSomethingWithResponse(networkService.response);
AnotherNetworkService anotherNetworkService = new AnotherNetworkService(result);
Needle.onBackgroundThread().serially().execute(anotherNetworkService);
But perhaps this is exactly the same as the AsyncTask.get() approach?

The TL;DR of any answer really will be: Kotlin coroutines.

Take a look at ScheduledThreadPoolExecutor which you can obtain like:
ExecutorService executor = Executors.newScheduledThreadPool(8);
There are numerous methods for scheduling futures.
Your first example might look like:
public class SomeActivity {
void onCreate() {
doSomething();
if (weNeedToDoSomeAsncTask()) {
executor.submit(() -> /* async task */);
doSomethingElse(response);
}
executor.submit(() -> /* different async task */)
afterAnotherAsyncTask();
}
}
(Although you'll need to look at the specific methods for alternatives to block/join.)

Related

How can I run a concurrent queue of tasks using Rx?

I've found a lot of examples about it and doesn't know what's the 'right' implementation right there.
Basically I've got a object (let's call it NBAManager) and there's a method public Completable generateGame() for this object. The idea is that generateGame method gets called a lot of times and I want to generate games in a sequential way: I was thinking about concurrent queue. I came up with the following design: I'd create a singleton instance of NBAService: service for NBAManager and the body of generateGame() will look like this:
public Completable generateGame(RequestInfo info)
return service.generateGame(info);
So basically I'll pass up that Completable result. And inside of that NBAService object I'll have a queue (a concurrent one, because I want to have an opportunity to poll() and add(request) if there's a call of generateGame() while NBAManager was processing one of the earlier requests) of requests. I got stuck with this:
What's the right way to write such a job queue in Rx way? There're so many examples of it. Could you send me a link of a good implementation?
How do I handle the logic of queue execution? I believe we've to execute if there's one job only and if there're many then we just have to add it and that's it. How can I control it without runnable? I was thinking about using subjects.
Thanks!
There are multiple ways to implement this, you can choose how much RxJava should be invoked. The least involvement can use a single threaded ExecutorService as the "queue" and CompletableSubject for the delayed completion:
class NBAService {
static ExecutorService exec = Executors.newSingleThreadedExecutor();
public static Completable generateGame(RequestInfo info) {
CompletableSubject result = CompletableSubject.create();
exec.submit(() -> {
// do something with the RequestInfo instance
f(info).subscribe(result);
});
return result;
}
}
A more involved solution would be if you wanted to trigger the execution when the Completable is subscribed to. In this case, you can go with create() and subscribeOn():
class NBAService {
public static Completable generateGame(RequestInfo info) {
return Completable.create(emitter -> {
// do something with the RequestInfo instance
emitter.setDisposable(
f(info).subscribe(emitter::onComplete, emitter::onError)
);
})
.subscribeOn(Schedulers.single());
}
}

In a Watcher in the fabric8 Kubernetes client events() API, what resources can I watch?

I am exploring the (undocumented?) events() API in Fabric8's Kubernetes client project.
Specifically, I see that I can do something like the following:
client.events().inAnyNamespace().watch(new Watcher<Something>() {
#Override
public final void eventReceived(final Action action, final Something something) {
}
#Override
public final void onClose(final KubernetesClientException kubernetesClientException) {
if (kubernetesClientException != null) {
// log? throw?
}
}
});
What are the permitted values of something and Something for something useful to happen? I'm assuming they are supposed to be things like Pods, Services, etc. but I'm not sure.
Watcher's sole type parameter is declared as <T>, so it would appear I could create a new Watcher<Integer>, but I'm willing to bet money that will never be called. This suggests that there is actually a bound in practice on <T>, but I don't know what it is, or why it would have been omitted if so.
If I had to guess, I'd guess from the parameter name, resource, that it would be something like T extendsResource<?, ?> but again, that's only a guess.
Thanks for any pointers, particularly to other documentation I'm sure I've missed.
Update #1: From banging around in the source code, I can see that the only place that a Watcher.Action's eventReceived() method is called forces the payload to be considered to be a HasMetadata object. Maybe that's my answer?
You can watch a particular pod or particular job for example. The T type in that case is Pod or Job respectively. Try
kube.extensions().jobs().createNew()...done().watch(new Watcher<Job>(){...})

Subscribe to an Observable without triggering it and then passing it on

This could get a little bit complicated and I'm not that experienced with Observables and the RX pattern so bear with me:
Suppose you've got some arbitrary SDK method which returns an Observable. You consume the method from a class which is - among other things - responsible for retrieving data and, while doing so, does some caching, so let's call it DataProvider. Then you've got another class which wants to access the data provided by DataProvider. Let's call it Consumer for now. So there we've got our setup.
Side note for all the pattern friends out there: I'm aware that this is not MVP, it's just an example for an analogous, but much more complex problem I'm facing in my application.
That being said, in Kotlin-like pseudo code the described situation would look like this:
class Consumer(val provider: DataProvider) {
fun logic() {
provider.getData().subscribe(...)
}
}
class DataProvider(val sdk: SDK) {
fun getData(): Consumer {
val observable = sdk.getData()
observable.subscribe(/*cache data as it passes through*/)
return observable
}
}
class SDK {
fun getData(): Observable {
return fetchDataFromNetwork()
}
}
The problem is, that upon calling sdk.subscribe() in the DataProvider I'm already triggering the Observable's subscribe() method which I don't want. I want the DataProvider to just silently listen - in this example the triggering should be done by the Consumer.
So what's the best RX compatible solution for this problem? The one outlined in the pseudo code above definitely isn't for various reasons one of which is the premature triggering of the network request before the Consumer has subscribed to the Observable. I've experimented with publish().autoComplete(2) before calling subscribe() in the DataProvider, but that doesn't seem to be the canonical way to do this kind of things. It just feels hacky.
Edit: Through SO's excellent "related" feature I've just stumbled across another question pointing in a different direction, but having a solution which could also be applicable here namely flatMap(). I knew that one before, but never actually had to use it. Seems like a viable way to me - what's your opinion regarding that?
If the caching step is not supposed to modify events in the chain, the doOnNext() operator can be used:
class DataProvider(val sdk: SDK) {
fun getData(): Observable<*> = sdk.getData().doOnNext(/*cache data as it passes through*/)
}
Yes, flatMap could be a solution. Moreover you could split your stream into chain of small Observables:
public class DataProvider {
private Api api;
private Parser parser;
private Cache cache;
public Observable<List<User>> getUsers() {
return api.getUsersFromNetwork()
.flatMap(parser::parseUsers)
.map(cache::cacheUsers);
}
}
public class Api {
public Observable<Response> getUsersFromNetwork() {
//makes https request or whatever
}
}
public class Parser {
public Observable<List<User>> parseUsers(Response response) {
//parse users
}
}
public class Cache {
public List<User> cacheUsers(List<User> users) {
//cache users
}
}
It's easy to test, maintain and replace implementations(with usage of interfaces). Also you could easily insert additional step into your stream(for instance log/convert/change data which you receive from server).
The other quite convenient operator is map. Basically instead of Observable<Data> it returns just Data. It could make your code even simpler.

Scheduler after return keyword

I have a method which opens a web service session. The method structure looks something like this:
public Soap getServicePort()
{
//TODO: Open a connect and return the SOAP object
return soap;
}
I have a requirement to add a monitor straight after the return. The monitor's job is to wait for 2hrs and in-activate the session and rebuild a new one - well reason been the current session will be invalid at that time and therefore we need to rebuild and return a new session.
Can anyone suggest a reasonable way of doing this?
Thanks.
public Soap getServicePort()
{
try {
return soap;
} finally {
// add monitor here.
}
}
But be careful: monitor should not throw exceptions. Put its initiation ito try/catch.
Probably better solution is wraper pattern. For example you can define interface with method getServicePort() and 2 implementations: one your real implementation and other that wraps real and adds monitor. This solution is more flexible. For example probably you will have to create your monitor afeter other methods and even after other methods implemented in other classes.
In this case you can use AOP. There are several ways to use it. One is using Dynamic Proxy of java. Other is using special tools like AspectJ.
So, choose your solution. Your choice should depend on the complexity of your task and number of methods/classes that required to implement this functionality. If it is only one method use try/finally, if it is several methods in the same class, use wrapper pattern. If it is required for several methods in several classes use Proxy or AspectJ.
You can try logic like this.. no need to have monitor on this
private Soap soap = null;
public Soap getServicePort()
{
try {
if(soap!=null && soap.isValide()){
// not sure about the method isValide(), some condition to check session
return soap;
}else{
// create new soap & return
return soap;
}
} catch(Exception e){
}// END Catch
}// END MEthod
Call the method as many times as you want...

Java: Asynchronous task

For some of HTTP requests from clients, there're very complex business logic in server side.
Some of these business logics doesn't require to response to the client immediately, like sending a email to somebody. Can I put those tasks in an asynchronous method,so I only need to ensure that they had been executed,I don't need to wait all tasks complete to respond to the user.
Updated: Some people asked about the framework I am using. I am using Struts2 + Spring.
You can use the following 'fire and forget' pattern:
new Thread(new Runnable(){
public void run(){
System.out.println("I Am Sending Email");
sendEmailFunction();
}
}).start();
But too many such threads will lead to trouble. If you are going to do this, then you should use a ThreadPoolExecutor to ensure that you have some control over thread production. At the very least, place a maximum on the number of threads.
I don't know what framework you're using, but, in basic Java, you can just create a new Thread:
interface MyTaskCallback {
void myTaskCallback();
}
class MyTask implements Runnable {
MyTaskCallback callback;
Thread me;
public MyTask(MyTaskCallback callback) {
this.callback = callback;
this.me = new Thread();
}
public void start() {
this.me = new Thread(this);
this.me.start();
}
public void stop() {
try {
this.me.join(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void run() {
// Calls here will not block the other threads
sendEmailRequest();
callback.myTaskCallback();
}
}
class Main implements MyTaskCallback {
public void foo() {
MyTask m = new MyTask(this);
m.start();
}
public void myTaskCallback() {
// called when MyTask completes
}
}
Yes. Read about concurrency.
You can probably set up an asynchronous producer/consumer queue, for example.
there is no "asynchroneous method" in java, but you will either use Threads (possibly through a framework like Quartz: http://www.quartz-scheduler.org/ ) or a message queue like JMS http://java.sun.com/products/jms/
You want to look at the java.util.concurrent.Executors. One way to solve your problem is to have a ScheduledExecutorService which keeps a Queue, and runs every so often. There are many different ways to offload work available in the concurrent utilities however, it depends on your requirements, how expensive the tasks are, how fast they need to be done, etc.
You should respond to all HTTP requests immediately, otherwise the client may think the server is not responding or timeout. However, you could start up other threads or processes to complete tasks in the background before you respond to the client.
You could also continue to send 100 responses until the task was complete.
Yes you can Servlet 3.0 has great asynchronous support.
Watch this its a really great resource, you can watch the entire cast if you are unfamiliar with Servlet 3.0.
A good run down of it here.
The api docs.
Spring has good support for Quartz scheduling as well as Java Threading. This link will give you better idea about it.
Can I put those tasks in an asynchronous method,so I don't need to wait all tasks complete to respond to the user ?
YES

Categories