I have a scenario and cant find reasonable answer. So posting the question directly !
Scenario -
I make a ajax request and send a file to be uploaded to the server.
On server(tomcat), I download the file and start processing it.
I run the download-file method on main thread and process-file method on new thread since it takes too long for processing and I dont want user to wait so long.
My Issue :
The Ajax response will catch the response in call back method for download-file method.
My process-file method also return the status response which I require to display on front-end when the processing is complete.
But I cannot because Runnable Interface has return type void for its run method.
Question -
How can I get result from process-file method and send in as response to front-end
If I am able to acheive above, how can I catch the response on front end javascript since main thread response will be caught in ajax success method already.
First: You can get result from process-file method by using Callable along with ExecutorService. Here is an example. And return to the front end is explaining below.
Second: As you do not want to wait user for process-file method so that you already return from main thread and you can not get second return by one single request. The following process make you to understand for better and easier solution for this situation.
Assign a id (e.g. UUID) for the process-file method. Pass it to the process-file method and return the id from main thread to front-end if successfully downloaded.
Then after processing your file, store in DB/wherever you want or put result in a Map<id, result> where id will be the key.
In front end you get the id for the process-file method. You can do call ajax request for certain interval to get the result of this id to a different endpoint (e.g. /file/status/{id}).
In that endpoint for retrieving result, you can get result from Map by id which is key of the Map or if you store in DB then you can easily get by the id and return it to front end.
In case you can not get result in Map/DB (in case of the file-processing not finished yet) you can send exception to frontend so that you can send request again after next interval.
Related
This question already has answers here:
How should I use servlets and Ajax?
(7 answers)
Closed 1 year ago.
As I understand it, when you wrap a servlet with a RequestDispatcher object and use the forward() method, you delegate that servlet to handle the request and produce the response. But what exactly is happening when you include an html page as an argument for getRequestDispatcher()?
This is from oracle:
RequestDispatcher getRequestDispatcher(java.lang.String path)
Returns a RequestDispatcher object that acts as a wrapper for the resource located at the given path. A RequestDispatcher object can be used to forward a request to the resource or to include the resource in a response.
https://docs.oracle.com/javaee/6/api/javax/servlet/ServletRequest.html#getRequestDispatcher(java.lang.String)
So where in the http response is this resource contained, how does the page receiving the response know to navigate to this page? And if the request was sent with AJAX, will the rest of the JS within that page be executed before redirecting to the new page? (i.e. If I'm writing a script that stores data from the response in a session, will this execute before the client navigates to another page?)
forward() means pass the request and response object to another servlet method.
The next servlet has 3 choices:
fill the response and send it to the client (even if the client has tried to use the previous servlet, it will receive the answer from that last servlet)
Make a redirect, which means that he sends to the client a message that says, please ask another url in order to be served.
Make another forward to another servlet, where the cycle starts again.
As you see the point of the servlet is to write something to the response that the client is going to receive. What happens with forward() is that the state of the response and request object is not lost when the control moves to the next servlet. This means that the 1st servlet can write something to the request object and then the 2nd servlet can write something new or edit something on the same request object.
For response object be careful though. You can write to the response by getting a reference to the writer by response.getWritter() . If the 1st servlet writes something using that writter the client will receive that message even if the control continues to move to the 2nd servlet. So you normally edit only the request object in the 1st servlet and then the 2nd servlet writes to the response object.
If you write an html code the client will receive an html response. If the client uses a browser it will render a web page.
Html code will not be packed as a resource file on the response. Html code must be written on that response object like every other field of an object that you write in java.
If i want to isolate a fetch request that returns a json in a separate file i should do?
opt 1.
Separate only the fetch request and return the response object, then in the call this function do response.json()
opt2
separate request and after run response.json() method and return the response.json from the function
Follow your second approach.
Best practice in every case to bundle your requirement into same function. So here - FETCH REQUEST, GET RESPONSE, CONVERT RESPONSE AS REQUIRED, RETURN RESPONSE must be in the same method.
For the part of the code that requires the data, it is in most cases not of interest how this data is retrieved (if it is requested from the server using fetch, using WebSocket, if it is cached in local storage, ...), so you normally don't want to return an object that is related to the type of transmission, but only the received data or a customer Result object that is not related to the API you use to request the data, but one that you define yourself.
That way you can easily change the transmission type at any time, add caching, offline functionalities, ... , and you don't need to change the parts of the code that is requesting the data.
I'm trying to scrape a site that uses lots of ajax effects to show data in a table.
There is some data returned via JSON when you interact with the site.
I know the URL and how to construct it but the server returns a HTTP 410 status if I try and re-request this JSON (I guess the server is expiring the data).
I have one chance to capture the data and I'm looking for a jQuery function, something like onJSONResourceReceived would be nice so that I can catch the response and store it in a variable.
Either a callback or a way to cache the data in a variable would be great.
Or if there is already a variable that stores all JSON resource already received in memory, that is even better.
All the functions I've looked at are for situations where you know or can re-request the URL.
This question is similar but for CasperJS:
How to get the response after a POST request in CasperJS
Look at the $.ajaxSuccess
Attach a function to be executed whenever an Ajax request completes
successfully.
$(document).ajaxSuccess(function( event, request, settings ) {
});
I have an AJAX call that is running a long PHP script where it has 20 different results, I would like to show when each step in the script is done.
Like so 1/20 done, 2/20 done, 3/20 done.
Latest 29-12-2015 03:17.
I tried to create the JSON file as so (jsonFileName_uniqueTimeStampHere.json) by PHP, but the time taken to create the file with PHP, result in a 404 file not found error!
Because when the AJAX call is running it comes to the progress call before the file has been created, I know I can't create the file with JavaScript but is there anyway to create.
The file before the success callback from jQuery AJAX?
What would be the best way to show progress information while AJAX call is running.
The way I have it now, I have a JSON file saved on the server that gets updated with the latest state that has completed, but if multiple users is running the same script the JSON file with the state gets overwritten.
Should I save the state of each progress in DB and then receive it with multiple calls to a PHP method that get state that has been completed?
Should I keep using the current method I use and add a userID to the JSON file so it is unique on each call to the file?
How should I go about doing it the same way as Seositecheckup?
What is the best way to make a progress with AJAX and PHP?
Please tell me if you need any more information.
I have looked around and don't feel like the info or half of info, there is to find online has been enough to do this myself.
I would like to use jQuery AJAX and not XMLHttpRequest, I'm looking for something similar to seositecheckup.com, when you scan a page you can see the state update on each completed function in the console and is done with different AJAX calls. How is that possible?
Should I forget about using jQuery and keep focus on plain JavaScript instead?
Right now I have a setup with jQuery that works the problem is, that I use a JSON file to get the result from and it gets overwritten when multiple users request the same script, is it possible to store the state in db instead and receive it from there with some unique identifier?
In the future I would like to make it possible to put the script into a queue that could be run and when the script ends it should send an e-mail to the user.
The HTTP way of handling requests that may take a long time is for requests to return a 202 and the body of the response should contain the URL where the user can query for the result.
#Request
POST /some/entitities
...
#Response
HTTP/1.0 202 Accepted
/jobs/{jobId}
The user can then poll /jobs/{jobId} which can return a number to represent progress. Do you have to use this? No, but if you do, others developers can immediately recognize what is going on.
Even if you don't use the approach I recommend, you will also have to keep track of job progress in your database and have a separate AJAX call to find out the current progress.
Let's imagine the situation that we've sent two similar (almost similar) async ajax requests to server one by one. Because of lag in network, the second request was executed before first request.
Ajax request #1: /change/?object_id=1&position=5
Ajax request #2: /change/?object_id=1&position=6
In result, we have object_id=1 position set to position=5, but we want position=6 because Ajax request #2 was executed after Ajax request #1 by us.
What is the best practice to avoid this on server side and client side?
Are you worried about racing conditions from the same client or from multiple clients?
If from the same client, I would think the safest bet would be to include a unix timestamp in the ajax request and log this value on the server. If a request comes with a timestamp that is older than the last logged value, ignore the request (or send a warning back to the browser).
I'm not sure how you would handle multiple clients with unsynchronized clocks...
For situations like this, I usually put a check in my success handler to make sure that the value being returned is still the one that I want. This will require sending up the parameter you're searching across in the results object.
For example:
var query = $('input').val();
$.get('/search', { query: query }, function(res) {
if(res.query == $('input').val()) {
//show search results
}
});
I don't know the particulars of your use case, but this general pattern should help.
On the server :
Build a request table to map request id to timestamp
Log any request to the server, expect all requests come with timestamp
If any request comes out of order (e.g. position 6 comes before 5)
Check the request table, if it is an earlier request (timestamp) then do not process the request and send an ignore flag
If it comes in order
This is fine, proceed as usual and no need to send any ignore order
On the client:
When request comes back in, check the ignore flag. If it is there. Don't do anything to the client
Otherwise proceed as usual by processing the data
Note that this implementation that I suggested requires you to send back and forth data (such as JSON) and not the presentation code (such as HTML fragment) as you would need to check for the ignore flag on the client side.
This answer is similar to what #Farray suggestion of using timestamp.