0

I am trying to design a Java Servlet for the first time. This is my final target behavior.

  1. Servlet receives a request.
  2. Servlet makes a HTTP Request to another server (Lets call it MServer).
  3. MServer can asynchronously send replies to my Servlets request within the next 20-25 mins.
  4. I want to send this data back to the user (who made the request to the servlet in step 1) as soon as the Servlet receives this data.

Any idea how I might do this?

As of now I have just made a "Hello World" Java Servlet. Also code to communicate with MServer is ready. But I dont know how can I achieve this asynchronous behavior.

Any help would be greatly appreciated.

yashdosi
  • 1,186
  • 1
  • 18
  • 40
  • 1
    Probably you need create some queue of messages on Servlet1 and retrive them using long polling http://stackoverflow.com/questions/11077857/what-are-long-polling-websockets-server-sent-events-sse-and-comet – Ostap Maliuvanchuk Apr 30 '14 at 14:15
  • So you are assuming the user is going to keep the tab open for 25 minutes while the page is waiting to load? Agreed with user979349, a polling system (in other words: an asynchronous design to match the asynchronous nature of your problem) is the way to go. – Gimby Apr 30 '14 at 14:34
  • @Gimby - Yes, I am assuming that the user would keep the connection open about 25 mins. – yashdosi May 02 '14 at 05:09
  • @user979349 - I dont want the user to do regular polling because in a smartphone this might be problematic for the power efficieny. And I want the user to be instantly notified as soon as servlet gets any data from MServer. – yashdosi May 02 '14 at 05:12
  • @Gimby - One more thing, I dont want a single reply at the end of 25 mins. I want multiple real-time replies for the same request. Something Like - User Request @ 0 mins. Servlet sends some data after 2 mins. Then maybe after 7 mins the servelet again sends some data without any action from the user. This happens every few mins. And after 25 mins client - servlet connection is terminated. And I dont want polling from client side. – yashdosi May 02 '14 at 05:39

3 Answers3

1

Here is a sample hope it helps. It assumes that you have a browser as a client and implements jQuery Ajax call. It checks every 5 seconds if your long running call from Mserver is done and data is available for client to use. I hope it helps you :)

Your servlet code:

public class TestServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String data = Mserver.getInstance().getData();

        response.setContentType("text/html;charset=UTF-8");
        response.setCharacterEncoding("UTF-8");

        PrintWriter out = response.getWriter();
        out.println(data);
    }
}

Sample Mserver code:

public class Mserver {
    private String data;
    private static final Mserver mserver = new Mserver();

    public static Mserver getInstance() {
        return mserver;
    }

    private Mserver() {
        new Thread() {
            @Override
            public void run() {
                computeData();
            }
        }.start();
    }

    // Computing data by making multiple server calls etc..
    private void computeData() {
        try {
            System.out.println("Waiting for 20 seconds simulating long running call");
            Thread.sleep(20000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        data = "Computed Data is ready now.";
    }

    public String getData() {
        return data;
    }
}

Html page using jQuery Ajax calls:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script src="js/jquery.min.js"></script>
<script type="text/javascript" charset="utf-8">
    $(document).ready(function() {
        setInterval(function() {
            $.ajax({
                type:"get",
                url: "checkDataFromMserver",
                async: false,
                success: function (data) {
                    $("#response").html(data);
                }
            });
        }, 5000);
    });
</script>
</head>
<body>
    Getting data using jQuery Ajax
    <div id="response"></div>
</body>
</html>

I tested it and it works. The client keeps polling every 5 seconds to check if data is ready. And after 20 seconds it gets it's data from Mserver.

Hope you find it useful!

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
vkg
  • 1,839
  • 14
  • 15
1

I think you should use an asynchronous servlet. I assume there is an MServer facade that looks like this:

interface MServer {
    void getStuff(Observer observer);
}

interface Observer {
    void onNewStuff(String stuff);
    void onThatWasAllStuff();
}

class MServerSingleton {
    MServer getInstance() {
        // Code that returns an MServer.
    }
}

Then you can implement your servlet something like this:

public class TheServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, final HttpServletResponse resp) {
        resp.setContentType("text/plain");
        final AsyncContext context = req.startAsync();
        MServerSingleton.getInstance().getStuff(new Observer() {
            void onNewStuff(String stuff) {
                try {
                    resp.getWriter().write(stuff + "\n\n");
                    resp.getWriter().flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            void onThatWasAllStuff() {
                context.complete();
            }
        });
    }
}

You will likely need to adjust timeouts for this to work.

You might want to consider using Server Sent Events.

PeakCode
  • 130
  • 7
0

You will probably have to implement a continuous check on the client's side and a queue on the server side. In other words the client will be contacting the servlet every 1-2 minutes to check for new messages addressed to him. The servlet should also have a method to get the data asynchronously and then store the recieved data in the queue. Implementing such queue can be done in many ways, for example by storing the responses from MServer in a database table.

Dropout
  • 13,653
  • 10
  • 56
  • 109
  • This cannot be addressed using plain Servlets since a Servlet attends a single request and commit a single response. You could use WebSockets instead for HTML 5 or a framework like [Atmosphere](https://github.com/Atmosphere/atmosphere) that enables this. – Luiggi Mendoza Apr 30 '14 at 14:40