Wait and notify on an object not working as I expected - java

I have a java servlet and am using jetty. On receiving a POST request, I am trying to send out another request to a different service. Upon receiving a response from the other service, I want to wake up my thread and continue sending the response. I am trying to use an object 'lock' to wait and notify. Can anyone tell why my thread doesn't wake up on lock.wait()?
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("application/json");
response.setStatus(HttpServletResponse.SC_OK);
Object lock = new Object();
client.newRequest("http://localhost:3699/create")
.method(HttpMethod.POST)
.content(new StringContentProvider(ServletUtils.extractRequestBody(request)))
.send(new BufferingResponseListener() {
#Override
public void onComplete(Result result) {
ServletUtils.forwardResponse(response, result, getContentAsString());
System.out.println("NOTIFY");
synchronized (lock) {
lock.notifyAll();
}
System.out.println("DONE NOTIFICATION");
}
});
try {
System.out.println("WAIT");
lock.wait();
System.out.println("DONE WAITING");
} catch (InterruptedException e) {
ServletUtils.badRequest(response);
}
}
My print statements say
WAIT
WAIT
NOTIFY
DONE NOTIFICATION
a) I'm not sure why I get 2 WAIT
b) I don't get to DONE WAITING

Related

Java AsyncContext start Runnable

I've created a Java servlet which does the following:
final AsyncContext aContext = request.startAsync();
aContext.start(new Runnable() {
public void run() {
HttpServletResponse response = (HttpServletResponse) aContext.getResponse();
try {
performRequest(proxyRequest, response);
} catch (IOException e) {
LOGGER.debug("IO Exception: " + e.getLocalizedMessage());
} catch (ServletException e) {
jsonResponse.append("ERROR", "Servlet Exception: " + e.getLocalizedMessage());
}
aContext.complete();
responseWriter.print(jsonResponse);
}
});
This servlet is called by a front-end UI which performs an AJAX call passing on some huge dataset.
The java servlet runs the method performRequest which can take up to a few minutes (on huge dataset).
I would like the servlet to return fast (the asynch process is triggered right away) otherwise the AJAX promise fails after 30 seconds wait.
What can I do?

How to implement Request Time Out in Web Application?

I am using spring and If request doesn't respond in 30Sec system should show Request Time Out Page.
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
logger.info("method=doFilter, Executing TimeoutFilter");
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
((HttpServletResponse) servletResponse).setStatus(HttpServletResponse.SC_GATEWAY_TIMEOUT);
try {
logger.warn("method=doFilter, Request timed out");
((HttpServletResponse) servletResponse).sendError(HttpServletResponse.SC_GATEWAY_TIMEOUT, "Request Timed out");
return;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return;
}
}, 30000);
filterChain.doFilter(servletRequest, servletResponse);
timer.cancel();
}
My new TimerTask function is getting called after 30sec, but problem is request is still running even after I return 504 status. So, I want to return 504 and end that request, Can you please suggest a solution for this

error: unreported exception InterruptedException; must be caught or declared to be thrown (calling AsyncTask)

This is my class that extends AsyncTask
public class JSONFunctions extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... urls) {
String line = "";
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet("http://appDev.milasevicius.com/server/homeresults.php");
try {
HttpResponse response = httpclient.execute(httpget);
if(response != null) {
InputStream inputstream = response.getEntity().getContent();
line = convertStreamToString(inputstream);
} else {
line = "Unable to complete your request";
}
} catch (ClientProtocolException e) {
line = "Caught ClientProtocolException";
} catch (IOException e) {
line = "Caught IOException";
} catch (Exception e) {
line = "Caught Exception";
}
return line;
}
protected void onProgressUpdate(Integer... progress) {
}
protected void onPostExecute(String result) {
}
}
And this is my call:
String output = new JSONFunctions().execute().get();
But compilator says that
error: unreported exception InterruptedException; must be caught or declared to be thrown
sorry for my noobish question, but how to fix that? And am I doing right call to get result?
public final Result get ()
Added in API level 3
Waits if necessary for the computation to complete, and then retrieves its result.
Returns
The computed result.
Throws
CancellationException If the computation was cancelled.
ExecutionException If the computation threw an exception.
InterruptedException If the current thread was interrupted while waiting.
get() throws InterrruptedException. Your log says you need to catch those.
Also you should not call get() coz its blocks the ui thread waiting fro the result. You should not block the ui thread.
Remove get() and invoke as new JSONFunctions().execute().
To get the result in the activity use a interface
Example #
How do I return a boolean from AsyncTask?
Javadoc
A bare InterruptedException being thrown from .get() indicates that the current thread of execution
(the one calling .get()) was interrupted before calling get(), or while blocked in .get().
This is not the same thing as an executor thread or one of its tasks being interrupted.
Someone or
something is interrupting your "main" thread -- or at least the thread calling .get().
Use
new JSONFunctions().execute()
instead of
new JSONFunctions().execute().get();

When response is delivered to client in asynchronous Servlets?

I'm having problems understanding how asynchronous servlets work, and in general how servlets deliver their response to the client.
What I'm trying to do is upload a video to a servlet via ajax. I thought that using an async servlet, I would obtain the response immediately in my browser and then the long task would be done in another thread.
I post my initial code here, before any code is written for file process, just an initial servlet to test asynchronism.
#WebServlet(name = "VideoUploader", urlPatterns = {"/VideoUploader"},
asyncSupported = true)
#MultipartConfig
public class VideoUploader extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
final PrintWriter pw = response.getWriter();
final AsyncContext ac = request.startAsync();
ac.setTimeout(80000);
ac.addListener(new AsyncListener() {
#Override
public void onComplete(AsyncEvent event) throws IOException {
System.out.println("On complete");
}
#Override
public void onTimeout(AsyncEvent event) throws IOException {
System.out.println("On timeout");
}
#Override
public void onError(AsyncEvent event) throws IOException {
System.out.println("On error");
}
#Override
public void onStartAsync(AsyncEvent event) throws IOException {
System.out.println("On start async");
}
});
ac.start(new Runnable() {
#Override
public void run() {
for (int i = 0; i <= 10; i++) {
System.out.println("Async task: "
+ Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
ac.complete();
}
});
pw.write("end");
pw.close();
}
}
Then, the client part is:
<form id="formVideo">
<label for="videoFile">VĂ­deo:</label>
<input id="videoFile" name="videoFile" type="file" /> <br/>
<input id="uploadVideoBtn" type="button" value="Subir" onClick="uploadVideo();"/>
</form>
<div id="notificaciones"/>
<script type="text/javascript">
function uploadVideo() {
var file = document.getElementById("videoFile").files[0];
var formdata = new FormData();
formdata.append("file", file);
var xhr = new XMLHttpRequest();
xhr.open("POST","/webapp/VideoUploader", true);
xhr.send(formdata);
xhr.onload = function(e) {
if (this.status == 200) {
alert(this.responseText);
}
};
}
</script>
When I didn't attach a video to the file input, the process is done as I expected, the response is immediately received in the browser. But when I attached a file of any size, my browser doesn't receive the response until the other thread is over.
I was researching on non blocking IO, but I'm not sure if it has something to do with this behaviour or not.
I'm still not sure how I want to implement this, although I'll listen to any advice, but what I would like is to understand the behaviour of this asynchronous servlets.
it is obivious, your browser will wait until the other thread completes. The following steps involved
Client Sent Request to Server
Server allocates Thread (Servlet Container) from ThreadPool
Servlet container creates Servlet instance / reuse existisng Servlet instance and invoke Servcie method in (Servlet Thread)
With in Service method by calling startAsync() will start new thread and pass the request,response instances to the new Thread to process the request note** New Thread is not blocking the http connection , it is just a thread in the jvm which is not bliocking any IO at this moment
Servlet Thread exists service method and returned to thread pool Note** here Response not yet sent to Client / Browser
Once the Process started in step 4 completed that thread will request Servlet Container to allocate to new Servlet thread to send the respond back to Client.
Only the at Step 6 the response will return back to Client. So there is no difference between the normal request and with "asyncSupported = true" from client point of view. Servlet 3.0 supports Threads per request by using "asyncSupported = true" instead of Thread per connection. Thread per connection will cause Thread Starvation.
#WebServlet(name = "VideoUploader", urlPatterns = { "/VideoUploader" }, asyncSupported = true)
#MultipartConfig
public class VideoUploader extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
#Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
final AsyncContext ac = request.startAsync();
ac.setTimeout(80000);
ac.addListener(new AsyncListener() {
public void onComplete(AsyncEvent event) throws IOException {
System.out.println("On complete");
}
public void onTimeout(AsyncEvent event) throws IOException {
System.out.println("On timeout");
}
public void onError(AsyncEvent event) throws IOException {
System.out.println("On error");
}
public void onStartAsync(AsyncEvent event) throws IOException {
System.out.println("On start async");
}
});
ac.start(new Runnable() {
public void run() {
System.out.println("Async task: "
+ Thread.currentThread().getName());
try {
for (Part part : ((HttpServletRequest) ac.getRequest())
.getParts()) {
System.out.println("File received"); // You Should write
// file here
// like
// part.write("fileName");
}
} catch (IOException e1) {
e1.printStackTrace();
} catch (ServletException e1) {
e1.printStackTrace();
}
ac.complete();
PrintWriter pw = null;
try {
pw = ac.getResponse().getWriter();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
pw.write("end");
pw.close();
}
});
}
}
Asynchronous servlet hands over the long running server side job to a different server thread. Non-Blocking IO, a new feature in servlet 3.1, deals with situation when incoming data is blocking or streamed slower than the server can read. Both are solutions to avoid servlet thread starvation. They are not about returning response to client immediately.
Since you are using Ajax, not a regular browser file upload, it should be easily implemented at the Ajax side with even a synchronous servlet, if you do not care about servlet thread starvation. Ajax is asynchronous in nature. Here is an example tutorial
http://www.javabeat.net/asynchronous-file-upload-using-ajax-jquery-progress-bar-and-java/

Is publishProgress method of AsyncTask asynchronous?

I've used AsyncTask quite a bit - but I have come across a seemingly simple question that confused me. The question is this:
Is publishProgress(Progress... values) supposed to return
immediately? In other words, is this method asynchronous?
Some Context:
I'm trying to determine whether the following code
Fires an HTTP request every three seconds, regardless of the response OR
Fires an HTTP request, waits for the response, and then sleeps for three seconds before firing the next request.
public class MyAsyncTask {
#Override
protected void doInBackground(String... params) {
while (mRunning) {
// Call publishProgress
this.publishProgress(makeHttpRequest());
// Sleep for 3 seconds
synchronized (lock) {
try {
lock.wait(3 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
return null;
}
private HttpResponse makeHttpRequest() {
HttpResponse ajaxResponse = null;
Throwable throwable = null;
try {
ajaxResponse = mHttpClient.execute(mHttpGet);
} catch (ClientProtocolException e) {
// Handle exception
} catch (IOException e) {
// Handle exception
} catch (Exception e) {
// Handle exception
}
return ajaxResponse;
}
#Override
protected void onProgressUpdate(HttpResponse... values) {
// Do something with the response
}
}
You're asking two different things here:
publishProgress() does indeed return instantly, it just posts a message to some Handler
Unrelated to how publishProgress() behaves, your code would always execute the HTTP request, wait for the response, then sleep three seconds. Just inlining method calls like publishProgress(makeHttpRequest()) doesn't mean that makeHttpRequest() isn't executed right where it's called, in your doInBackground() method.
this.publishProgress(makeHttpRequest());
is equals to (Java can't pass methods. Just the results)
HttpResponse resp = makeHttpRequest();
this.publishProgess(resp);
so makeHttpReqest is done in the background.
You than pass the HttpResponse Object to publishProgress which returns immediately. The progress Object is then asynchronously send to onProgressUpdate() in the UI thread.
-> it's the then sleeps way.

Categories