1

I've been working on a react app. In this app, I will be sending the input from the user to the Java servlet on the tomcat server to sort it. After sorting, I'm trying to display it on a label in my react app. I've successfully sent it to the java servlet using fetch method() and sorted it.

This is how my fetch() method looks like:

 const [text, setText] = useState("");
  async function onSubmit() {
 
    var newText = { text: text}; //object
      await fetch(`http://localhost:8080/backend/link`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "Access-Control-Allow-Origin" : "*",
 "Access-Control-Allow-Credentials" : true,
 "status" : 200
        },
        body: JSON.stringify(newText),
        mode: 'no-cors',
      })
        .then((response) => {
        console.log("response");
        console.log(response.body); //displays null
        })
        .then((data) => {
        console.log(data);
          console.log("Success");
        });
    }

My Java servlet looks like this:

public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException
{
System.out.println("invoked");
String jsonBody = new BufferedReader(new InputStreamReader(request.getInputStream())).lines().collect(
           Collectors.joining("\n"));
System.out.println(jsonBody);
if (jsonBody == null || jsonBody.trim().length() == 0) {
       return;
   }
   JSONObject jObj;
try {
jObj = new JSONObject(jsonBody);
String lines[] = ((String) jObj.get("text")).split(","); //The words in the input are separated by comma
Arrays.sort(lines);
for (String a : lines)
           System.out.println(a);

response.setContentType("application/json");
   response.setCharacterEncoding("UTF-8");
   
} catch (JSONException e) {
System.out.print("Exception");
}
}

whatever I send in the response object (Using Printwriter), the fetched response's body is null. How can I send the array so that I can get it in the response object of the fetch and then display it in a label?

Please leave your suggestions

  • 1
    Looks like you are not adding the lines array to the response, just printing them out to debug. Confirm there is no body by looking at the response from the server in the browser's developer tools. – Dave Jan 08 '22 at 14:59
  • @Dave No I tried sending some JSON response using PrintWriter and tried to display the response on the browser's console and the response body was empty. I want the data to be on the response body so that I can access it and display it on a label later – Sharon Shelton Jan 08 '22 at 15:06
  • @Dave I've removed those lines to avoid confusion(since i just used them for testing). – Sharon Shelton Jan 08 '22 at 15:08
  • @Dave I can see the content-length of my response. Can you please tell me how can I access the content from the response in the fetch() API so that I can display it on a label? – Sharon Shelton Jan 08 '22 at 16:03

3 Answers3

1

I do not see where you write the body in the servlet response.

Perhaps you need something like this:

final PrintWriter writer = response.getWriter();
for (String a : lines)
           writer.println(a);

Note: your client is expecting a JSON object back, so you probably want to write your jObj to the output and not lines of text.

Use google chrome debug to view response headers of your network request. There you can see the body of the response. My guess is that your client-side code is fine and the server is not sending any content in the body.

enter image description here

Dave
  • 7,552
  • 4
  • 22
  • 26
  • I tried to send some dummy data to the client(not the sorted list), yet I don't get to see anything on the response tab. – Sharon Shelton Jan 08 '22 at 18:15
  • The response tab says, "Failed to load response data: No data found for resource with given identifier" Can you help me with the JSON conversion part? I don't quite get it – Sharon Shelton Jan 08 '22 at 18:18
  • As we expected. The servlet isn't returning the data. Make the most dumb servlet possible to get it returning a JSON object. Then build it back up to return the JSON you want. This may help: https://stackoverflow.com/questions/2010990/how-do-you-return-a-json-object-from-a-java-servlet – Dave Jan 08 '22 at 18:20
  • ```final PrintWriter writer = response.getWriter(); JsonObject json = new JsonObject(); json.addProperty("Hi", "Hello"); writer.print(json.toString());``` Did something like this and still getting the same message on the resonse tab. Did I do it right? – Sharon Shelton Jan 08 '22 at 18:33
  • Looks good, but it's been a very long time since I've played with java. Confirm the response status is "200 ok" and and check if you see any errors in the javascript debug console related to "cors". Now that you have the above I'm running out of ideas. – Dave Jan 08 '22 at 18:50
  • That's alright. You really spent a lot of time to help me. Thank you so much. Yeah, I've checked for the cors error. And the status code is 200. The Content-Length: 14 in the response header returns the correct length of the response. But couldn't figure out why I couldn't see the body of the response – Sharon Shelton Jan 08 '22 at 19:05
  • I figured out that it is has something to do with the "no-cors" mode – Sharon Shelton Jan 09 '22 at 04:19
  • I've answered my question. Please do check it out. And thanks for providing me some vision on how to actually check the response on the client side. It was really helpful – Sharon Shelton Jan 11 '22 at 10:45
1

From your code it's not clear how did you use PrintWriter. You can try something like below and then check the response:

String message = new ArrayList<String>();
PrintWriter writer = response.getWriter();
JSONObject obj = new JSONObject();
obj.put("message",message); 
response.setStatus(200);
writer.append(obj.toString());
writer.close();

Put a string message on JSON object to check whether nothing is being passed or only response is not being passed. Call "response.message" to fetch the message on client side.

  • writer.close() may be the missing bit. – Dave Jan 08 '22 at 19:09
  • I still don't get the response on the client :( – Sharon Shelton Jan 08 '22 at 19:24
  • print response on console and see what all present in it. (Don't print response.body) – Divyanshu Pandey Jan 08 '22 at 19:43
  • @DivyanshuPandey ```Response {type: 'opaque', url: '', redirected: false, status: 0, ok: false, …} body: null bodyUsed: false headers: Headers {} ok: false redirected: false status: 0 statusText: "" type: "opaque" url: "" [[Prototype]]: Response``` – Sharon Shelton Jan 09 '22 at 03:54
  • I don't have hands-on on React Framework but what I can guess is you are initializing "text" from a blank 'useState'. For your reference you can checkout these links: (https://www.geeksforgeeks.org/what-is-usestate-in-react/) (https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) – Divyanshu Pandey Jan 09 '22 at 05:40
0

It was because I used "no-cors" mode in the client side which means that JavaScript cannot access the properties of the resulting response. Here's a detailed explanation about it: https://stackoverflow.com/a/43319482/13893049 . I've done several modifications on the client side as well as the server side including changing the content type from application/json to text/plain since json format is not among one of the allowed types.

The only allowed values for the Content-Type header are:

application/x-www-form-urlencoded
multipart/form-data
text/plain

Now my client side code looks like this:

    var newText = { text: text, commands: new_list.join(), reg: reg };

      await fetch(`http://localhost:8080/backend/link`, {
        method: "POST",
        headers: {
          "Content-Type": "text/plain",
          "Origin" : "http://localhost:3000/",
        },
        body: JSON.stringify(newText),
      })
        .then((response) => response.text())
        .then((data) => {
          //console.log("Success");
          //console.log(typeof data);
          setRes(regex(data));
        });
  }

(I've added few variables for my requirement)

From the server side I'm sending back an array in the form of string. I'm answering my own question since someone in the future might find in helpful. Do let me know in the comments if you got any doubts.

  • 1
    I should have alerted you to cors sooner. You can use the content-type you want, but then your server-side should respond to OPTIONS method. Ultimately, it is your server-side code that will return extra headers telling the browser that it's OK to let the javascript see the response. https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS – Dave Jan 11 '22 at 15:30