I have an android service that has a set of operations :
MyService.java
public class MyService extends Service {
public int login() {
//Invokes yet another logic to initiate login and waits for result
//synchronously and returns status code based on result of operation
}
public int logout() {
//Invokes yet another logic to initiate logout and waits for result
//synchronously and returns the status code
}
}
I am invoking the methods from a client activity say, MyClientActivity.java residing in the same process.
For each operations the service invokes some logic and waits for the result in a synchronous manner. When the service is executing all of this logic I do not want the user to perform anything else and just show a loading screen. So basically, after I have initiated an operation I want MyClientActivity to wait for the status code synchronously. Now I know that I cannot block the UI thread to avoid ANR.
How can I make this operation execute on a separate thread and then get the result back so that I can appropriately propagate the result back to the user by changing the UI based on this result.
I am pretty new to this and can't really grasp the concepts. If someone can explain along with an example that would be helpful.
In Android there are plenty ways to do asynchronous work like you desccribed. You can use a Service, a Loader, if you're using Retrofit library for network requests, than it has async requests built in, so follow the documentation. Also, there is RxJava, but it's learning curve quite steep.
I accomplished this by using a HandlerThread to create a Handler to which I am posting Runnables to do the background tasks.
To do that main thread tasks (UI tasks) I am using mainLooper to create another Handler to which I posts Runnables to do operations on views.
A rough representation of the code :
mBackgroundHandler.post(new Runnable() {
#Override
public void run() {
//Do background operation in synchronous manner as usual.
mMainHandler.post(new Runnable() {
#Override
public void run() {
//Remove loader, update UI
}
});
}
});
Related
I have an API endpoint /api1 that will make 2 service calls -
insertIndb(), called on certain inputs
verify(), called on certain inputs
I want to return the response of insertIndb() to the caller when they call /api1 only and not the verify() call. The verify() call if called, the caller need not wait for the response of this call but just get something like response in process. Since the goal of verify() is to update db and not return back anything.
So I was suggested to make this verify call in background. How can I do that?
Summarizing my flow below:
Enduser send POST /api1 with payload entity.
If entity does not exist,
the /api1 will make a insertIndb() call and return the response to the end user as 200.
After this, It will call /verify in background, the enduser need not wait for the response. // How to do this?
If entity exists,
It will only call /verify in background, the enduser need not wait for the response. // How to do this?
Probably return just 200 on your request is submitted.
How to run the above /verify calls in background based on the above flow is my question. Could anyone please help me here?
There are multiple ways to may a non-blocking fire-and-forget call like this.
The simplest, IMO, is to use a separate thread to execute the call using a synchronous operation. Another is to use tooling that supports non-blocking calls.
In addition, there are frameworks that simplify this effort. Camel comes to mind. Of course, there is a fair amount of effort to use the framework itself.
You can achieve this by using #EnableAsync annotation in spring by following way:
#SpringBootApplication
#EnableAsync
public class MyApplication {
public static void main(String[] arg) {
SpringApplication.run(MyApplication.class);
}
}
then you need to mark the emailUserInTheBackground method with #Async annotation.
#Service
class AnotherService {
#Async
public void verify(int userId) {
try {
TimeUnit.SECONDS.sleep(10);
System.out.println("Print from async: "+ Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Now add one more logger after a method call, you'll see getUsers(...) call completing first in a different thread even though the emailService thread is blocked for 10 seconds.
anotherService.verify();
System.out.println("Print from service: "+ Thread.currentThread().getName());
Also, there is CompletableFuture for achieving non blocking coding . You can read more about this in below link
https://www.javatpoint.com/completablefuture-in-java
I am writing a service where I want to expose an endpoint which will call another service and if the service call is successful then I want to send back the result to UI/ calling app.
In parallel before sending back the response, I want to execute/submit a task which should run in background and my call should not be dependent on success or failure of this task.
Before returning the response i want to do the-
executorService.execute(object);
This should not be a blocking call..
Any suggestion
Spring Async methods is the way to go here as was suggested in comments.
Some caveats:
Async methods can have different return types, its true that they can return CompletableFuture but this is in case if you called them from some background process and would like to wait/check for their execution status or perhaps, execute something else when the future is ready. In your case it seems that you want "fire-and-forget" behavior. So you should use void return type for your #Async annotated method.
Make sure that you place #EnableAsync. Under that hood it works in a way that it wraps the bean that has #Async methods with some sort of proxy, so the proxy is actually injected into your service. So #EnableAsync turns on this proxy generation mechanism. You can verify that this is the case usually in the debugger and checking the actual type of the injected reference object.
Consider customizing the the task executor to make sure that you're running the async methods with executor that matches your needs. For example, you won't probably want that every invocation of async method would spawn a new thread (and there is an executor that behaves like this). You can read about various executors here for example
Update
Code-wise you should do something like this:
public class MyAsyncHandler {
#Async
public void doAsyncJob(...) {
...
}
}
#Service
public class MyService {
#Autowired // or autowired constructor
private MyAsyncHandler asyncHandler;
public Result doMyMainJob(params) {
dao.saveInDB();
// do other synchronous stuff
Result res = prepareResult();
asyncHandler.doAsyncJob(); // this returns immediately
return res;
}
}
I have a case to be implemented in my project.Below is a sample rest service which has to be implemented
#GET
#Path("/test/{id}")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public String getData(#PathParam("id") String id) {
//Some processing to get value of String
String result = doSomeProcessing();
//I want to return this result to GUI and call one more rest api
// and end this process without waiting for response from second
//call
new Thread(){
//call second rest api
}.start();
return result;
}
Is this good approach using new Thread to call second rest API and return result without waiting for response from second rest API ?
I have also looked into Asynchronous Rest call, but it doesn't exactly suit my requirement. Please advice. Thanks in Advance
Avoid starting Threads directly. Consider an ExecutorService instead as shown below:
#Singleton
#Path("foo")
public class FooResource {
private ExecutorService executor;
#PostConstruct
public void onCreate() {
// Creates a thread pool that reuses a fixed number
// of threads operating off a shared unbounded queue
this.executor = Executors.newFixedThreadPool​(10);
}
#GET
public Response getFoo() {
String result = doSomeProcessing();
// Submits a Runnable task for execution
executor.submit(new LongRunningTask());
return Response.ok(result).build();
}
#PreDestroy
public void onDestroy() {
// Initiates an orderly shutdown in which previously submitted
// tasks are executed, but no new tasks will be accepted.
this.executor.shutdownNow();
}
}
public class LongRunningTask implements Runnable {
#Override
public void run() {
try {
// Simulate a long running task
// Don't do it in a real application
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Explore the Executors API for details on how to create an ExecutorService instance.
In Java SE and in a Servlet container, you can use an ExecutorService for your long running task. In a Java EE container, you should use a ManagedExecutorService instead:
#Resource
ManagedExecutorService executor;
Once it's a resource managed by the container, you don't need to instantiate and dispose it manually.
I not sure what do you exactly mean by "calling the second REST API" so I assume that you're sending an HTTP request to another external API, i.e "second REST API".
You can use Apache HC to send the request and skip waiting for the response. See its fluent API which is easy to use. Async.execute is the one that ought to be used in your case. The Async class uses a thread-pool underneath to handle background requests.
I should mention that I haven't used any other HTTP client libraries. There might be other choices out there with almost the same functionality.
Side Note I strongly suggest ExecutorService, esp. ThreadPoolExecutor instead of creating new threads. It has more control over life-cycle of threads and manages system resource efficiently. ExecutorService has methods for fire and forget scenarios (submit). However, this only makes sense when your "second REST API" call is actually implemented in another method in your application and lives within the same JRE.
I'd say yes and no; there is nothing "wrong" about calling another service asynchronously (ex: a metrics subsystem to register that a call to that service was made). However, I wouldn't create threads straight in the getData method, I would use another (injected) object to hide the implementation detail (ex: just calling some sort of myOtherService.submit(something). That way you can easily switch from something synchronous, to asnychronous and even change the async method to your liking.
As to the actual implementation, instead of creating threads, I would submit callables to an executor service instead so you save the overhead of creating actual system threads, or you could even have one or more threads waiting on a blocking queue and just put jobs in that queue for threads to pick them up.
I am using CXF to call web service. It is used in a simple way like it is described in the documentation:
HelloService service = new HelloService();
Hello client = service.getHelloHttpPort();
String result = client.sayHi("Joe");
How can I terminate this service call when it takes time?
I found only one related question but this doesn't provide any solution.
How to terminate CXF webservice call within Callable upon Future cancellation
I think this is more of a function of the web server. For example, if you use Jetty to serve your CXF content, then you can set the thread pool to something that'll watch your threads.
ThreadPoolExecutor pool = new ThreadPoolExecutor(...);
ExecutorService svc = new ControlledExecutorService(pool);
server.setThreadPool(new org.eclipse.jetty.util.thread.ExecutorThreadPool(svc));
Then for the custom executor service (sorry, all code typed in the browser directly. I'm on an iPad with no Java. So you'll likely need to make slight adjustments, but the useful parts should be here):
public class ControlledExecutorService implements ExecutorService {
private ExecutorService es;
public ControlledExecutorService(ExecutorService wrapped) {
es = wrapped;
}
#Override
public void execute(final Runnable command) {
Future<Boolean> future = submit(new Callable< Boolean >() {
public Boolean call() throws Exception {
command.run();
return true;
}
});
// Do the proper monitoring of your Future and interrupt it
// using Future.cancel(true) if you need to.
}
}
Be sure to pass true to cancel() so that it sends the interrupt.
Also remember than just like with any thread, just because you send it an interrupt, it doesn't mean it'll comply. You have to do some work in your threads to make sure they're well behaved. Notably, periodically check Thread.currentThread().isInterrupted() and properly handling InterruptedException to pick it up and stop the task gracefully instead of just letting the exception blow everything up.
I have a situation wherein I call a method which in turn triggers a asynchronous HTTP REST call(sends the status later to another endpoint) before it proceeds further. I want the method to wait until i get the response back to the endpoint, check the status i got and proceed further. I am looking for a feasible solution in Java. Any pseudo code or implementation will be helpful
saw similar case # Lightweight way of waiting for a group of asynchronous Java calls but not much idea about the same whether it is easy to implement.
Implementation details
I have JAX-RS endpoint to handle the async response as below
#POST
#Path("/status")
#Consumes("application/xml")
public Response processConfigStatus(#Context UriInfo uriInfo, ConfigStatus configStatus)
{
// process Status got from the async REST call
return ResponseHelper.createNoContentResponse();
}
Class which handles and processes
Class ProcessData{
public void updateData()
checktStatus(uri);
update();// should wait untill the processConfigStatus() endpoint gives status
}
private checktStatus(String uri){
// makes a REST call to a URI using a JAX-RS webclient or a httpclient this returns HTTP 200 or 204 code immediatley. And then the Server process the request asynchronously and gives back the status to JAX-RS endpoint(/status).
post(uri);
}
}
Method call from another Class
ProcessData pd = new ProcessData()
pd.updateData();
How about using a CountDownLatch?
A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
Just as in the link you provided, you'll have to implement a way to simply keep track of how many async calls are stilling waiting for a response and wait until that count is zero.
count = numAsyncCalls
..calling all of the RESTful services here (each call must have some sort of callback to decrement 'count' variable above..
while (count > 0)
wait around
The use of the CountDownLatch in your link looks pretty much the same as my pseudo-code