-4

My question comes from this code.

In short, it does:

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException 
{    
    response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();
    try
    {
        out.println("<html>");
        out.println("<head>");
        out.println("<title>Hi World</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("<h1> Hello World </h1>");
        doPost(request,response); // <<--- ???
        out.println("</body>");
        out.println("</html>");    
    } 
    finally 
    {
        out.close();
    }
}

I know it is just a sample code. But in the case I'm a newbie and make this "doPost inside a doGet stuff because I read it on SO and I think it is ok": what are the problems with doing this? is it ineficient (hitting the server twice for a no good reason)? fires unnecessary requests on the server? too much unnecesary code (for both the doPost and doGet methods)? is it utterly nonsense? or, maybe, there are scenarios when doing this is reasonable?

Community
  • 1
  • 1
Broken_Window
  • 2,037
  • 3
  • 21
  • 47
  • If your webapp does mostly the same with both a get and a post, your options are to either replicate the code (wasteful, prone to error), call one in the other (easy way), or create a helper method that handles both (long-term way). – Compass Dec 15 '14 at 15:36
  • If for some reason you need both to do the exact same thing, then calling the other *and doing nothing else but calling the other* makes some sense. But doing what is being done above is horrible. Not just that they are doing other things before and after calling the other, but printing out HTML in a servlet like that is just bad. – developerwjk Dec 15 '14 at 22:48

3 Answers3

1

You have to first understand that doPost and doGet are just methods.

is it ineficient (hitting the server twice for a no good reason)

You're not hitting the server. You're invoking a method. It'd be the same as writing a separate method foo(..) and invoking that.

The doPost and doGet (and others) are part of the Servlet API which tries to simplify your life by giving you entry points to handle specific request types.

If both the handlers do the exact same thing, don't repeat the same code. Put it one method and call it from the other. Or better yet, extract the logic to a completely different method and invoke that from both.


Flow of a Servlet container (YMMV):

  1. Server accepts Socket connection.
  2. Server dispatches thread to handle request
  3. Thread parses request headers and bodies and prepares ServletRequest and ServletResponse objects.
  4. Thread determines Servlet/Filter route. (This is where it would determine your Servlet is appropriate.)
  5. Thread invokes HttpServlet#service(..).
  6. That invocation delegates to the appropriate doXYZ method in your subtype.
  7. Stack rewinds as invocations complete, thread does cleanup of request and commits response.
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
0

The client (the browser) doesn't notice which methods you call in your server code.

In this case, you reuse code from doPost() to avoid duplication in doGet() which is good.

The problem is that doPost() comes with some strings attached. In this case, it changes the response headers. This won't always work: If the server code has started to send the response, changed to header fields are silently ignored. So the code will work if there it an output buffer and as long the buffer is big enough. A small change can make the code break in unexpected and hard to understand ways.

A much better solution would be split the code into helper methods which are called by doGet() and doPost().

In fact, in my old code, I had an abstraction layer between the Servlet API and my code. My code would get a map for header fields plus a Writer for the output. That way, it was trivial to test the code (like switching the map with something that throws exceptions when you call put() after the first character was written to the Writer).

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
0

To illustrate what others already wrote, the simplest way to handle this is:

doGet(...) {
   processRequest(...);
}

doPost(...) {
    processRequest(...);
}

processRequest(...) {
    ...
}
Predrag Maric
  • 23,938
  • 5
  • 52
  • 68