3

I would like to recursively call a servlet from itself until my operation completes. The reason I need to do this is because my hosting service has a hard deadline that must be met for all RPC calls. Therefore, I need to break up the operation in managable chunks and call the servlet recursively for each chunk until the operation completes.

I feel like the following code should work, but it is not calling the servlet when the HttpURLConnection is opened and connected. No errors are being thrown either. Any help would be greatly appreciated.

import java.io.DataOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@SuppressWarnings("serial")
public class ServletExample extends HttpServlet {

HttpServletRequest request;

public void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {

    request = req;

    String strRequestIndex = request.getParameter("requestIndex");
    int intRequestIndex = 0;

    if (strRequestIndex != null) {
        intRequestIndex = Integer.parseInt(strRequestIndex);
    }

    if (intRequestIndex < 10) {
        try {
            callSameServlet(intRequestIndex);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

private void callSameServlet(int requestIndex) throws Exception {

    URL recursiveUrl = new URL(request.getRequestURL().toString()
            + "?requestIndex=" + (requestIndex + 1));

    HttpURLConnection connection = (HttpURLConnection) recursiveUrl
            .openConnection();

    connection.setRequestMethod("POST");
    connection.setDoInput(true);
    connection.setDoOutput(true);
    connection.setUseCaches(false);
    connection.connect();

    DataOutputStream dos = new DataOutputStream(
            connection.getOutputStream());

    dos.flush();
    dos.close();

}

}
Fishbone
  • 41
  • 1
  • 3
  • In callSameServlet you request with POST but overrides HttpServlet.doGet(). Is that correct ? – PeterMmm Nov 22 '10 at 15:24
  • 2
    if call 1 performs call 2, doesn't call 1 need to wait for call 2 to finish? Unless I'm missing something, your strategy is flawed. – Buhb Nov 22 '10 at 15:52

1 Answers1

2

As to the technical problem as exposed in your question: the URLConnection is lazily executed. The URLConnection#getOutputStream() in your code only returns a handle to write the request body. You need to use URLConnection#getInputStream() to actually fire the HTTP request and obtain the response body.

See also:


There are however more problems in your code:

You're firing a POST request, but there's nowhere a doPost() method in your servlet definied. You need to either fire a normal GET or to implement doPost(). But that'll be obvious by investigating the obtained error response as described in the above link.

Also, your servlet is not threadsafe. You should never declare/assign request/session scoped data as instance variable of the servlet. Read this answer to learn more.

Finally, did you consider using RequestDispatcher#include() instead? That will be handled internally and saves you the cost/overhead of firing HTTP requests.

request.getRequestDispatcher("servleturl").include(request, response);

You can then use request attributes instead of request parameters. The whole functional requirement makes little sense by the way. I'd just use a for or while loop on the code you'd like to execute recursively. But that's a different problem.

Community
  • 1
  • 1
BalusC
  • 992,635
  • 352
  • 3,478
  • 3,452
  • +1: the second part of your answer is very similar to what I thought about this. – Tomas Narros Nov 22 '10 at 16:10
  • Thanks for the help. I did try to use RequestDispatcher but I received an InvalidState error. It seems that the response was already committed and therefore I was unable to perform any operations such as forwarding or redirecting the response. – Fishbone Nov 23 '10 at 05:21
  • 1
    Then there's more into the code than you have shown in the question. You should not commit the response before the last iteration. – BalusC Nov 23 '10 at 11:07