So, in my app, I send the request from http server handler
to another server. The thing is the second server is stuck on reading object. I was trying to figure out it myself but I can't see the problem. All streams are closed, maybe the response to the client is in the wrong place? I have no idea why is that..
This is my client:
public class ClientSimulator { private Random random; private static int clientCounter = 1; public static void main(String[] args) throws Exception { new ClientSimulator(); new ClientSimulator(); new ClientSimulator(); } private ClientSimulator() { this.random = new Random(); RuntimeMXBean rmb = ManagementFactory.getRuntimeMXBean(); long arrivalTime = rmb.getUptime(); System.out.println("thread no. " + clientCounter++ + " arrival time: " + arrivalTime); try { String myurl= "http://localhost:8080/sender"; String serverResponse = createClient(myurl); System.out.println(serverResponse); } catch (Exception e) { e.printStackTrace(); } } private String createClient(String myurl) throws Exception { URL url; BufferedReader reader = null; StringBuilder stringBuilder; try { //Standard HTTP connection url = new URL(schedulerUrl); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setDoInput(true); connection.setDoOutput(true); int[] arr = { random.nextInt(10-1)+1, random.nextInt(10-1)+1, random.nextInt(10-1)+1, random.nextInt(10-1)+1, random.nextInt(10-1)+1, }; Task t = new Task(arr); ObjectOutputStream oos = new ObjectOutputStream(connection.getOutputStream()); oos.writeObject(t); oos.close(); // read the output from the server reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); stringBuilder = new StringBuilder(); //print the response String line = reader.readLine(); stringBuilder.append(line); return stringBuilder.toString(); } catch (Exception e) { e.printStackTrace(); throw e; } finally { if (reader != null) { try { reader.close(); } catch (IOException ioe) { ioe.printStackTrace(); } } } } private boolean getRandBool(){ return this.random.nextBoolean(); } }
This is how I send the request from the main server to another server:
@Override public void handle(HttpExchange httpExchange) throws IOException { String template = "\nClient no. %s connected!"; //Getting task Task t; ObjectInputStream ois = new ObjectInputStream(httpExchange.getRequestBody()); try { System.out.print("Recieved object:"); t = (Task) ois.readObject(); t.setDeadline(deadline); t.setHard(isHard); System.out.print(" not sorted array: "); int[] arr = (int[]) t.getData(); for (int anArr : arr) { System.out.print(anArr + " "); } ois.close(); String response = "response for client no. " + clientCounter; httpExchange.sendResponseHeaders(200, response.length()); OutputStream os = httpExchange.getResponseBody(); os.write(response.getBytes()); os.close(); clientCounter++; HttpURLConnection test = (HttpURLConnection) new URL(fogServ1URL).openConnection(); test.setDoOutput(true); System.out.println("test__1"); ObjectOutputStream stream = new ObjectOutputStream(test.getOutputStream()); stream.flush(); System.out.println("test__2"); stream.writeObject(t); System.out.println("test__3"); stream.close(); System.out.println("test__4"); test.getResponseCode(); System.out.println("test__5"); //this doesn't print } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
This is handler from the second server:
class RootHandler implements HttpHandler{ private static int clientCounter = 1; @Override public void handle(HttpExchange exchange) throws IOException { System.out.println("\nRoot handler; \n\tclient no. " + clientCounter++); Task t; ObjectInputStream ois = new ObjectInputStream(exchange.getRequestBody()); try { System.out.println("Recieved object:"); //only this is on the console t = (Task) ois.readObject(); ois.close(); System.out.println("Array not sorted:"); int[] arr = (int[]) t.getData(); for (int anArr : arr) { System.out.print(anArr + " "); } TaskSolver.solve(t); System.out.println("\nArray sorted!"); for (int anArr : (int[])t.getData()) { System.out.print(anArr + " "); } } catch (ClassNotFoundException e) { e.printStackTrace(); } String response = "Server up!"; exchange.sendResponseHeaders(200, response.getBytes().length); OutputStream os = exchange.getResponseBody(); os.write(response.getBytes()); os.close(); } }
I don't get it because I send the Task
from client to the main server in the same way and its working. I just can't read the output in the next servers. What am I doing wrong?
Btw. If someone is curious why I'm sending the same object to another server: I plan to create more servers, the main server will be sending requests to them depending on type/containing headers.
2 Answers
Answers 1
In Second server while reading the object there is some IOException occurred, since IOException in handle method of RootHandler class is passed to invoking method instead of handling it. So error like Internal Server Error
response status is sent to client ( first server ).
Since there is exception in second server the test.getResponseCode()
throws IOException since it is not handled in first server handle
method
System.out.println("test__5");
is not invoked.
If you want to know what is happening catch IOException in handle method of the both server and print Stack trace.
Answers 2
Try following below sequence in your first server -
- Receive object by reading the
InputStream
- Connect with the second server.
- Send object by writing on
OutputStream
of second server. - Get the response from second server
- Send response to client by writing on
OutputStream
of first server.
The reason behind current behavior is related to closing of Exchange
. As per the documentation -
Exchanges are terminated when both the request InputStream and response OutputStream are closed.
Currently, in your first server code, you are writing the response on OutputStream
and then closing it. After that, your first server start communicating with second server.
When first server sent request to second server and wait for the response, at the time, underlying HttpExchange
gets closed, thus connection and associated thread are released. Till this time, second server hasn't read the request.
In this situation, some IOException
must occur in second server for indicating the error or second server will keep waiting for reading the InputStream
and eventually get timeout.
Closing of Exchange
and releasing of associated thread is not immediate step after closing OutputStream
, but it can terminate anytime and subsequent code lines are not guaranteed to be executed. In your case, connection terminated while waiting for the response from second server but it can terminate before that also.
0 comments:
Post a Comment