Call db from async method - java

I have a Controller that must accept a request and do not wait for the finishing of the processing, give a response.
#PostMapping
#ResponseStatus(HttpStatus.CREATED)
public void processEvent(#RequestBody RequestMyObjectDTO requestMyObjectDTO) {
MyProcessor.process(requestMyObjectDTO);
}
After I give a response, I must execute the processing.
#Async
public void process(RequestMyObjectDTO myRequestObject) {
List<TestObject> testObjects= repository.findAllTestObject();
if (testObjects.isEmpty()) {
return;
}
.............
Is there any difference in where I will go to the database, in the asynchronous method, or outside it? In my case in Controller for example.
How it will impact behavior and what approaches are better?
Given that I need a check:
List<TestObject> testObjects= repository.findAllTestObject();
if (testObjects.isEmpty()) {
return;
}
At the same time, I expect that the controller may receive millions of requests.

Related

Spring boot call async while others in progress

I have a requirement where I am validating a data hitting a rest call like
#Async
private void validate() throws WebClientResponseException {
this.webClient.method(HttpMethod.GET)
.uri(urlBuilder -> urlBuilder.path(uripath).build())
.retrieve()
.bodyToMono(Response.class).block();
// throws exception in case of validation failure
}
I am calling this function from another function
RETURN_TYPE func() {
validate();
//rest of the code and validations
service.save(input);
}
My requirement is validate() should be called asynchronously and rest of the code and validations should be called parallelly.
It should not execute service.save() until both of them finishes. Is it possible to do that?

RxJava: Create an Observable during HTTP Request that keeps running after request returns

I have an HTTP request that triggers a long-running task (multiple HTTP requests to another service) that is supposed to be completed in the background while the original requests complete.
So what I do is
public void triggerWork(#RequestBody SomeObject somObject) {
return new ResponseEntity<>(startWorkAndReturn(somObject), HttpStatus.OK);
}
public void startWorkAndReturn(SomeObject someObject) {
Observable.create(observableEmitter -> {
// do the work with someObject here and at some time call
observableEmitter.onNext("result");
}).subscribe(new Observer<Object>() {
#Override
public void onSubscribe(Disposable disposable) {
}
#Override
public void onNext(Object o) {
// called at some unknown time
}
#Override
public void onError(Throwable throwable) {
}
#Override
public void onComplete() {
// currently not used as all the work is done in onNext but maybe that's a mistake
}
});
return;
}
But this seems to block the request until all the work has been done. Which already seems odd to me, since I never call onComplete, which in itself might be a mistake. But still, I am wondering how to create a request that immediately returns after triggering a background worker.
Is Flowables the solution here? I am going to refactor to those anyways to handle backpressure. Or do I need to create a background worker Thread? What is the best practice here?
Thanks
I would use Observable.fromCallable{} since you need emit only single event. That will handle onCompleate call. From information you share I don`t know how can you properly handle disposable. You should add subscribeOn() and observeOn() operators that will define on which thread 'work' should be processed and result should be observed.
Docs ref:
http://reactivex.io/RxJava/javadoc/io/reactivex/Observable.html#fromCallable-java.util.concurrent.Callable-
http://reactivex.io/documentation/operators/subscribeon.html
http://reactivex.io/documentation/operators/observeon.html

How to implement wait in a method call in generic way

I am trying to implement a generic solution for third party API(work in async way) but not getting any idea that how i can implement a call for rest of my application in synchronized way. Basically API is working like take request, process it and then give response when it finish but in meanwhile open to receive other requests as well. So i put API response method in a thread so that monitor continuously either there is a response or not by calling api response method with time interval.
API have interface to take request like:
public void api_execute(string UUID,String request);
API response object:
public APIReponse
{
private String UUID;
private String response_string
// Getter setter
}
I want to write a wrapper on top of this API in which have a single method so that different objects of my application use this to send request and receive response. so UUID will be create by this wrapper class but i am not getting that how i will wait a caller object until i received some response and also distinguish which caller send which request. I was thinking by using observer pattern here but seems to be not fit with this scenario. Can someone give me a hint how i can implement this.
You create async task executor using thread pool
ExecutorService threadpool = Executors.newFixedThreadPool(3);
public Future<APIReponse> submitTask(APIRequest request) throws InterruptedException, ExecutionException {
System.out.println("Submitting Task ...");
Future<APIReponse> future = threadpool.submit(new Callable<APIReponse>() {
#Override
public APIReponse call() throws Exception {
api_execute(request,UUID);
return new APIReponse();
}
});
return future;

How to make concurrent network requests using OKHTTP?

I'm looking for a best practice for making concurrent network requests using the OKHTTP library.
Basically here's what I want to do:
I want to write a method that makes N concurrent network requests to different URLs, and return ONLY when ALL N requests have returned.
I thought about manually writing Threads and Runnables and such to create a group of request pool, but was wondering if there's some sort of easier way to do this. So my question is:
Does OKHTTP support concurrent request API natively somehow?
If not, what's the best way to implement this?
OkHttp natively supports asynchronous requests efficiently e.g. sharing the optimum number of connections.
See https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/AsynchronousGet.java
For the second part of the question, you use a CountdownLatch or you can bridge to java Futures like the following
public class OkHttpResponseFuture implements Callback {
public final CompletableFuture<Response> future = new CompletableFuture<>();
public OkHttpResponseFuture() {
}
#Override public void onFailure(Call call, IOException e) {
future.completeExceptionally(e);
}
#Override public void onResponse(Call call, Response response) throws IOException {
future.complete(response);
}
}
And call
private Future<Response> makeRequest(OkHttpClient client, Request request) {
Call call = client.newCall(request);
OkHttpResponseFuture result = new OkHttpResponseFuture();
call.enqueue(result);
return result.future;
}
At that point you can use methods like CompletableFuture.allOf
n.b. if you wrap with Futures, it can be easy to not close the Response objects when one fails.

How to retrieve result of an #Async method

I have a small Spring Boot app waiting for REST calls to start an async job. However what I'd like to do next is get results of those async jobs and store them in DB. But I don't know how to use object returned with Future asynchronically.
Here is more or less what I have:
#RequestMapping("/vlan/{id}/{name}")
public void performVLANConfig(#PathVariable("id") int id, #PathVariable("name") String name) {
logger.debug("Received req");
Future<ProcessedRequest> processedRequestFuture= asyncService.processVlan(id, name);
processedRequestRepository.save(processedRequest);
}
But now it just waits for async call to end. Is there any way to let the async method live its life and after it has completed store this completition error?
You need to attach a callback. If you using Future then you can't attach a callback to it, assign to a ListenableFuture instead, the service needs to return a ListenableFuture of course.
ListenableFuture<ProcessedRequest> future = asyncService.processVlan(id, name);
future.addCallback(new ListenableFutureCallback<ProcessedRequest>() {
#Override
public void onFailure(Throwable throwable) {
// deal with it
}
#Override
public void onSuccess(ProcessedRequest processedRequest) {
processedRequestRepository.save(processedRequest);
}
});

Categories

Resources