views:

1194

answers:

3

Hello - I'm unable to figure out what is going on here in this ultra simple example.

Problem Summary: I have a simple servlet that appears to run just fine if I drive it manually... by issuing its URL from the browser. By 'just fine' I mean: I can see in the browser HTML page whatever I write in the servlet response.

However, if I issue the very same URL via Ajax code, the servlet processes the request fine and even 'appears' to be writing out the response fine ... but, just that I do not see any response on the Ajax client code side and thus neither in my browser HTML page.

Further, if I make my XHR request syncrhonous, the browser error console shows the following exception:

*Error: uncaught exception: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIXMLHttpRequest.send]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: file:///home/sd/Desktop/test.html :: callServlet :: line 35" data: no]*

Environment:

Browser: Firefox 3.5.3

Servlet container: Tomcat 6.0.20

OS: Linux / Fedora 11

Ajax code:

<!-- test.html -->
<html>
<head>
  <script>
var req;

function $(id) {
  return document.getElementById(id);
}

function servletCallback() {
  var field = $("debugHtmlId");
  field.innerHTML += "readyState='" + req.readyState + "'<br> ";
  field.innerHTML += "status='" + req.status + "'<br> ";
  field.innerHTML += "responseText='" + req.responseText + "' | <br> ";
}

req = new XMLHttpRequest();
req.onreadystatechange = servletCallback;

    function callServlet() {
      // With async mode off, I get the
      // Exception listed above.
      //    req.open("GET", "http://localhost:8080/aaa/bbb?f=test", false);

      req.open("GET", "http://localhost:8080/aaa/bbb?f=test", true);
      req.send(null);

    }
  </script>
</head>
<body>    
  <input id="callserv" type="submit" value="Call Servlet" onclick="callServlet();" />
  <span id="debugHtmlId"></div>
</body>
</html>

Servlet code:

// servlet code
public class MyServlet extends HttpServlet {
  public void doGet(HttpServletRequest req, HttpServletResponse rsp)
      throws ServletException, IOException {

    rsp.setContentType("text/html");

    String val = req.getParameter("f");
    if(val.equals("test")) {
      // Increment value.
      ++_count;

      // Return value.
      PrintWriter out = rsp.getWriter();
      out.printf("%d\n", _count);
      out.close();

      // This shows up fine in servlet log.
      System.out.printf("%d\n", _count);
    }
  }

  // This variable is incremented and returned on each call to doGet().
  private int _count = 0;
}

EDIT:

  1. Including the result: Here's what I see for example as the value of my innerHTML of my debugHtmlId element.

    readyState='1' readyState='1' readyState='2' status='0' responseText='' | readyState='4' status='0' responseText='' |

  2. Strange behavior: Notice also that my readystatechange handler is getting re-entered! I mean, I was expecting to see readyState='...' status='...' responseText='...' triads for every state change...

A: 

Try this: Don't call out.close(); on the PrintWriter. Instead, call out.flush();.

Jesper
Had tried it already, never worked. In fact, I read somewhere that we're supposed to use close() and not flush()... otherwise, the ajax side remains under the impression that more stuff is on the way. That was the reason, I replaced flush() with close().
Harry
A: 

The problem was: I had loaded the above HTML in my browser not from the Tomcat/web server but from my local file system. I thought, for development I won't need to deploy the HTML to the server.

Since what I originally wanted works fine now, I'm not so worried now about the exception I was getting in the sync mode of ajax.

Harry
Regarding the exception you were getting - Firefox does indeed give this error whenever sync mode is used for Ajax calls because sending a sync request blocks the execution and waits for the reply thus making the UI unresponsive to the user. So practically there is no meaningful use-case scenario for a sync Ajax request. However, other browsers like IE/Chrome/etc. allow this behavior without throwing an error.
Vuk
A: 

I look at the code and did two things to work on my CentOS 5 Linux dev box with Tomcat5:

  1. Modified the code and rename my servlet to eServlet:

    req.open("GET", "http://localhost:8080/aaa/bbb?f=test", true);
    

    to

    req.open("GET", "eServelet?f=test", true);
    
  2. Modified WEB-INF/web.xml and added servlet mapping

    <servlet>
        <servlet-name>eServletApps</servlet-name>
        <servlet-class>eServlet</servlet-class>
    </servlet>
    
    
    <servlet-mapping>
        <servlet-name>eServletApps</servlet-name>
        <url-pattern>/eServlet</url-pattern>
    </servlet-mapping>
    
  3. Compiled with command:

    # javac -classpath $CATALINA_HOME/common/lib/servlet-api.jar eServlet.java
    
  4. Loaded it and it Works without any problems

Kitara Lagony