Cancel a running service request in springboot - java

I am new to Springboot and I am trying to cancel a request that was posted from the UI to the gateway.
There are 2 API's - the first one is the gateway and the other is an extractDataApi.
I am trying to cancel the request from the UI to extract data and return a 'Cancelled by user message'. The scenario is the gateway api receives the request and calls the service in the extractDataApi. While this service is running how can I send another request to stop this service and return a message? How can I achieve this? Is there a built-in method that can take care of this?

Related

How to connect http request with async response from message broker

Problem:
In my api-gateway I call other microservices using a message broker and wait for response using method, annotated using Spring #MessageHandler. When response arrives how am I suppose to connect it with the waiting http request?
My solution is to hang request to CompletableFuture, generate a unique key and save the CompletableFuture with the key to the Spring Data Key-Value (or other in-memory) database and than call other services via Message Broker and send my request key along with the data. When async response arrives to the MessageHandler, check the in-memory database for my request key that is also part of the response and complete the stage.
If there are more nodes in cluster, I'll use a topic and check every key-value instance and complete stage only on the correct node, since I don't want to use any distributed cache for that.
Is it a good solution? Or how do you handle this particular problem?

What Asynchronous connection really means in inter-dependent JAVA application

I am building an application which connect with other too. For the application I need to take a request from a websocket connection. Once i received the request need to send the request to some other application for processing and there will be few cases.
If second application return accepted then wait for a response from 3rd application (3 will send response to 2nd and 2nd will initiate a push model).
If second application return other than accepted then return false to the request
My confusion is, this way I will handle the request as synchronous or asynchronous ?
As in case #1 I have to wait for some time to receive response from another application. more over in case #2 I can immediately process a request.
Sequence diagram for clarity of flow

Reactive Streams: Spring WebFlux - subscribe to existing publisher

I am currently migrating our existing Spring asynchronous REST architecture to Spring's new WebFlux library and have a question around joining multiple requests so that they can listen for the same published response.
Use Case is as follows:
Client A connects to our web server and requests data
We hit our cache to check if we have the data there
We don't, so we go and retrieve this data (Client A has subscribed and waits for a response)
Client B connects to our web server and requests the same data (hits the same endpoint)
We check the cache, data is still not there
As we are already fetching this data for Client A we don't want to make another request, however, we also do not want to turn Client B away. Client B should be able to listen for the same information
How can Client B subscribe to the same response stream that Client A is waiting for?
"Client A has subscribed and waits for a response"
I suppose the request is coded as a Mono and client A sibscribes to it literally:
Subscriber<Response> clientA = ...
Mono<Response> request = makeRequest(...);
request.subscribe(clientA);
then clientB should subscribe the same way:
Subscriber<Response> clientB = ...
request.subscribe(clientB);
Moreover, the cache should contain not the previously saved response data, but the requests themselves, of type Mono<Response>. Then, if such a request is found in the cache, new clients simply subscribe to it, regardless of was that request already completed or not.

How to create Ajax request that gets information as the servlet runs?

I have a form that creates an account and a servlet that handles the request.
However, the process to create this account is a long process and I want to create something like a status bar or a progress bar. Heres the POST:
$.post("createAccount.jsp", function(data) { $("#status").text(data);
});
And the servlet would continuously print data like "creating x..." then "creating y" as the servlet runs. Is there a way to accomplish this or maybe another way to tackle this issue?
Thanks
Http works on a request-response model. You send a request, and server responds back. After that Server doesn't know who are you?!
It's like Server is a post-office that doesn't know your address. You
go to it and get your letters.It doesn't come to your home for
delivering letters.
If you want constant notifications from server, You can either use Web Sockets(Stack Overflow also uses Web Sockets) or use `AJAX Polling' mechanisms,
which sends an AJAX request to the server and waits for server to
respond. On retrieval of response,it generates another AJAX request
and keep on doing the same until server stops generating new data.
Read this for an explanation of AJAX Polling techniques
You could have your account creation servlet update a database or context attribute as it creates the account.
You could have a separate AJAX request to a different servlet that sends back to the webpage the most recent development found in the database or context attribute. You would then poll your server with that AJAX request every so many fractions of a second(or relevant time interval depending on how long of a task it is to create an account) to get all the updates.

Call a Web Service from Servlet at AppEngine

Question: What is best way to call a web service (0.5-1.5 seconds/call) from a servlet at AppEngine? Are blocking calls are scalable at AppEngine environment?
Context: I am developing a web application using AppEngine and J2EE. The applications calls Amazon web service to grab some information for the user. From my asp.net experience, best way to do the calls - is to use async http handler to prevent starvation at IIS thread pool. This feature is not available for J2EE with Servlet 2.5 spec (3.0 is planned).
Right now I am thinking of making my controllers (and servlets) thread safe and request scoped. Is there anything also that I can do? Is it even an issue in J2EE + AppEngine environment?
EDIT: I am aware of AppEngine and JAX-WS async invocation support, but I am not sure how it play with servlet environment. As far as I understand, to complete servlet request, the code still should wait for async WS call completion (callback or whatever).
I assume that doing it using synchronization primitives will block current working thread.
So, as far as thread is blocked, to serve another user request servlet container need to allocate new thread in thread pool, allocate new memory for stack and waste time for context switching. Moreover, requests can block entire server, when we run out of threads in thread pool. This assumptions are based on ASP.Net and IIS thread model. Are they applicable to J2EE environment?
ANSWER: After studying Apache and GAE documentation, it seems that starvation of threads in the thread pool is not a real issue. Apache, by default has 200 threads for thread pool (compared to 25 in asp.NET and IIS). Based on this I can infer that threads are rather cheap in JVM.
In case if async processing is really required or servlet container will run out of threads, it's possible to redesign the application to send response via google channel api.
The workflow will look like:
Make sync request to servlet
Servlet makes creates channel for async reply and queues task for background worker
Servlet returns response to client
[Serving other requests]
Background worker does processing and pushes data to client via channel api
As you observe, servlets don't support using a single thread to service multiple concurrent requests - one thread is required per request. The best way to do your HTTP call is to use asynchronous urlfetch, and wait on that call to complete when you need the result. This will block the request's thread, but there's no avoiding that - the thread is dedicated to the current request until it terminates no matter what you do.
If you don't need the response from the API call to serve the user's request, you could use the task queue to do the work offline, instead.
Isn't it OK to use fetchAsync?
looks at this, this might help
http://today.java.net/pub/a/today/2006/09/19/asynchronous-jax-ws-web-services.html
I am not sure, If you can exactly replicate what you do in dot net, Here is what you could do to may be to simulate it page on load
Submit an ajax request to controller using a java script body onload
In the controller start the async task and send the response back the user and use a session token to keep track of the task
You can poll the controller (add another method to ask for update of the task, since you have session token to track the task) until u get the response
You can do this either waiting for response page or hidden frame that keeps polling the controller
Once you have the response that you are looking for remove the session token
If you want to do that would be the best option instead of polling would be ideal in this case Reverse Ajax / server push
Edit: Now I understand what you mean, I think you can have your code execute async task not wait for response from async itself, just send response back to the user. I have simple thread that I will start but will wait for it to finish as I send the response back to the user and the same time use a session token to track the request
#Controller
#RequestMapping("/asyncTest")
public class AsyncCotroller {
#RequestMapping(value = "/async.html", method = RequestMethod.GET)
public ModelAndView dialogController(Model model, HttpServletRequest request)
{
System.err.println("(System.currentTimeMillis()/1000) " + (System.currentTimeMillis()/1000));
//start a thread (async simulator)
new Thread(new MyRunnbelImpl()).start();
//use this attribute to track response
request.getSession().setAttribute("asyncTaskSessionAttribute", "asyncTaskSessionAttribute");
//if you look at the print of system out, you will see that it is not waiting on //async task
System.err.println("(System.currentTimeMillis()/1000) " + (System.currentTimeMillis()/1000));
return new ModelAndView("test");
}
class MyRunnbelImpl implements Runnable
{
#Override
public void run()
{
try
{
Thread.sleep(5000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}

Categories