Cannot send an object through an object output stream from one http handler to another

So, in my application, I am sending a request from the http server handler to another server. The fact is that the second server is stuck on reading the object. I tried to figure it out myself, but I don't see the problem. All threads are closed, maybe the answer to the client is in the wrong place? I do not know why this is so.

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 a 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 the 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 do not understand, because I send Task from the client to the main server in the same way and its work. I just can't read the output on the following servers. What am I doing wrong?

Btw. If someone is wondering why I am sending the same object to another server: I plan to create more servers, the main server will send them requests depending on the type / containing headers.

+5
source share
2 answers

On the second server, an IOException error occurs while reading the object, because the IOException method in the RootHandler method is passed to the calling method instead of processing it. Thus, an error message like Internal Server Error sent to the client (first server).

Since there is an exception on the second server, test.getResponseCode() throws an IOException because it is not handled in the first server's handle method

System.out.println("test__5");

not called.

If you want to know what is happening, catch an IOException in the server descriptor and print stack trace method. A.

0
source

Try the following sequence on the first server -

  • Get an object by reading an InputStream
  • Connect to the second server.
  • Send object by writing to the OutputStream of the second server.
  • Get a response from the second server
  • Send a response to the client by writing to the first server's OutputStream .

The reason for the current behavior is due to the closure of Exchange . According to the documentation -

Exchange stops when both the InputStream and Response OutputStream requests are closed.

Currently, in your first server code, you write a response to an OutputStream and then close it. After that, your first server will begin to communicate with the second server.

When the first server sends a request to the second server and waits for a response, then the underlying HttpExchange closed, so the connection and the associated stream are freed. Until this time, the second server did not read the request.

In this situation, some IOException should appear in the second server to indicate an error or the second server will continue to read the InputStream and eventually get a timeout.

Closing Exchange and releasing the associated stream is not an immediate step after closing the OutputStream , but it can OutputStream at any time and subsequent lines of code are not guaranteed. In your case, the connection terminates awaiting a response from the second server, but it can also end before that.

0
source

Source: https://habr.com/ru/post/1274924/


All Articles