Long polling with AJAX and Spring works unstable - java

I have a web page which polls data from server with long polling. My javascript code is:
function getData(){
$.ajax({
url: "graph.htm",
type:"POST",
dataType:"json",
timeout: 30000,
success: successFunc,
complete: getData
});
}
function successFunc(data, textStatus){
console.log(data);
//......
}
and I have a Controller on server,which checks every second, if database is modified and if it is - it sends the data:
#RequestMapping(value = "/graph", method = RequestMethod.POST)
public void graphPOST(HttpServletResponse response) {
while(!daoService.isModified()){
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
try {
String jsonData = daoService.getJsonData();
response.setContentType("application/json");
response.setHeader("Cache-Control", "no-cache");
response.getWriter().write(jsonData);
System.out.println("=== sent!");
} catch (IOException ex) {
ex.printStackTrace();
throw new RuntimeException("IOError writing file to output stream");
}
}
And usually it works fine. BUT sometimes (maybe, one time from ten) i have the situation:
Data is sent from server (I see the meessage "=== sent!" in console).
Client gets nothing (javasrcipt console is clear, there are no messages from console.log()).

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?

Java ExecutorService REST call error

I am trying to use Java's ExecutorService to send out concurrent REST requests which make various logs of system information (coming from a controller), however am running into a bug. About half of my requests successfully make it to the target, but the other half appear as if they are sent, but are not found on the server they were sent to. I think I may have a flaw in the logic of setting up my ExecutorService. The function log() shown below can be called from a REST call to the controller, and is supposed to create a new thread which sends out a separate HTTP request, and continue with the main thread so as not to wait for the network I/O. After much searching, I believe I have the ExecutorService shutdown properly an wait for the thread to complete. Can anybody see some type of error in the logic of my thread creation, as multiple requests from the controller can continue to come in?
//Controller
//code
#RequestMapping(value="/log", method= RequestMethod.GET)
public String log()
{
genomicsLogger.log(Severity.err, Category.LOG, "This is a log from the reporting manager!");
return "Hopefully logged";
}
//ClassB
public String log(String trns , String user, Severity severity, Category category, String msg) {
trnsField = trns;
userField = user;
...
...
...
ExecutorService executor = Executors.newFixedThreadPool(1);
Runnable task = () -> {
try {
System.out.println("Started thread: " + Thread.currentThread().getName());
restService.consumeRest(true, instance.getUri().toString(), LOG_URI, list, log, HttpMethod.POST, new HttpHeaders(), String.class);
System.out.println("SENT REST REQUEST");
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
}
};
executor.submit(task);
try {
System.out.println("attempt to shutdown executor");
executor.shutdown();
executor.awaitTermination(5, TimeUnit.SECONDS);
}
catch (InterruptedException e) {
System.err.println("tasks interrupted");
}
finally {
if (!executor.isTerminated()) {
System.err.println("cancel non-finished tasks");
}
executor.shutdownNow();
System.out.println("shutdown finished");
}
return "";
}
You are creating executor service with each log and killing it.
This is not the way to use it, it is meant to be reused, make it e.g. a field in this class and set some number of threads that you are willing to use for it (probably higher than 1). And don't do shutdown on it until you are really sure it won't be used (e.g. during application shutdown).

Server-sent event lost connection

I'm following this tutorial and I'm putting the returned data on console log in Chrome. Here is my code on client side:
$(document).ready(function() {
//check for browser support
if(typeof(EventSource)!=="undefined") {
var source = new EventSource("URL/sse");
//detect message receipt
source.addEventListener("message", function(e) {
console.log(e.data);
}, false);
source.addEventListener("open", function(e) {
console.log("Connection was opened.");
}, false);
source.addEventListener("error", function(e) {
if (e.readyState == EventSource.CLOSED) {
console.log("Connection lost.");
}
}, false);
}
else {
// No support
}
});
The data is ok. When I access the webpage, my console log is opening and closing the connection every 3 seconds:
mypage.js:39 Connection was opened.
mypage.js:15 [{"John":"1","Doe":"2"}]
mypage.js:44 Error - Connection lost.
// 3 seconds
mypage.js:39 Connection was opened.
mypage.js:15 [{"John":"1","Doe":"2"}]
mypage.js:44 Error - Connection lost.
// 3 seconds
mypage.js:39 Connection was opened.
mypage.js:15 [{"John":"1","Doe":"2"}]
mypage.js:44 Error - Connection lost.
...
Here is my server-side code:
#Singleton
#Path("/sse")
public class SSEResource {
#GET
#Produces(SseFeature.SERVER_SENT_EVENTS)
public EventOutput getServerSentEvents() {
final EventOutput eventOutput = new EventOutput();
new Thread(new Runnable() {
#Override
public void run() {
try {
final OutboundEvent.Builder eventBuilder = new OutboundEvent.Builder();
eventBuilder.name("message");
final String myString = getData.toString(); // Some data from db
eventBuilder.data(String.class, myString);
final OutboundEvent event = eventBuilder.build();
eventOutput.write(event);
} catch (Exception e) {
throw new RuntimeException("Error when writing the event.",
e);
} finally {
try {
eventOutput.close();
} catch (IOException ioClose) {
throw new RuntimeException(
"Error when closing the event output.", ioClose);
}
}
}
}).start();
return eventOutput;
}
}
From what I understand, the connection should remain open until the client decided to close it. What am I doing wrong? Is that correct?
Your server code is closing the EventOutput.
try {
eventOutput.close();
} catch (IOException ioClose) {
throw new RuntimeException(
"Error when closing the event output.", ioClose);
}
This causes the client to reconnect and the process starts again.
I'm not 100% sure what you are doing. If you want to send more data in the thread, you need to not close the EventOutput.
According to the specification you can send a HTTP 204 No Content response code to prevent the client from reconnecting, I'm not sure how to do this using Jersey SSE though. I was searching for the answer when I came across this question.
In your case you could send a message that causes the client to close the connection, or prevents it from reconnecting.

How can I use GET-request to get a sentence from http-server

I am working on a project that consists in making connection between two http-agents via http-protocol. So I am writing a java-program for that purpose. the client will send a GET-request to get a sentence from the http-server. That http-Server is a simple java-program, in which we find the following instruction:
final String id="03788444"
My Aim is to get this id from the server using GET-requet. My small Java Server is running on localhost at port 80. Basically my resource is that id, so I write the following:
GET /id HTTP/1.1
But I get nothing from the server.
From the server-side I wrote the following:
"http/1.1 200 OK"
blankline
id
is it correct?
should I put the id in a txt-file and send the file by using http-protocol. I think that id is not a resource. So I should put it in a file???
public class Server {
....
void send_response(){
try {
out= new PrintWriter( socket.getOutputStream());
//status line
out.print("http/1.1 200 OK");
//blank line!!!
out.print("");
out.print(id);
}catch (IOException e) {
e.printStackTrace();
}
}
void close_connection(){
out.close();
}
}
public class Client {
....
void sendGet(){
final String request_line="GET /id http/1.1";
PrintWriter out = null;
.....
try {
out = new PrintWriter(ag_socket.getOutputStream(), true);
// Send request to http-agent
out.println(request_line);
out.println(); // blank line separating header & body
} catch (IOException e) {
e.printStackTrace();
}finally{
//out.close();
}
}

java.net.ProtocolException: Cannot write output after reading input

I am trying to send the object from applet to struts action class
using object output stream but it gives me a exception java.net.ProtocolException: Cannot write output after reading input.
I created a new instance of URLConnection to giving specific url
and tried to write object in url to send the struts action class from applet
i am calling this method on save button click of applet
public saveDesign()
{
try
{
HttpURLConnection urlConnection = getServletConnection(CallServletConnection.SAVE_DESIGN, null);
// Pragma = no-cache; should be null
if(urlConnection != null && urlConnection.getHeaderFields().get("Pragma") != null)
return false;
OutputStream outstream = urlConnection.getOutputStream();//Exception occur here
ObjectOutputStream objectoutstream = new ObjectOutputStream(outstream);
objectoutstream.writeObject("abc");
objectoutstream.flush();
objectoutstream.close();
System.out.println("vctObjectDetails is write ");
}
catch (MalformedURLException exception) {
exception.printStackTrace();
}
catch(ConnectException exception) {
exception.printStackTrace();
}
catch (IOException exception) {
exception.printStackTrace();
}
catch(Exception e)
{
e.printStackTrace();
}
}
but it doesn't work.
Please gives me some tips if anyone knows how to handle this exception.
It all has to do with the lifecycle of an HTTP request (which is what HttpURLConnection abstracts) - once the request has been sent, you cannot modify it any further - in case you have more data to send, you just make another one.
What is happening underneath is that once you call getHeaderFields() (the response header fields), the 'HttpURLConnection' sends the request and makes the response available.
I don't know what is in 'getServletConnection()', but you could try using 'doOutput()' and not reading from the response, until you have finished writing to the request.

Categories