1

I came across my posts which answer this question.But i am not able get an idea of how i can implement in my program.My requirement is as follows.

from a jsp page i call a servlet using ajax call:

$(document).on('click' , '#gettopevents' , function(event) {


            var field = $("input[name = 'field']").val(); 

            if(field === "")
            {
                $('#responsemsg').html("enter a field");
            }
            else
            {
                var dataform = { 'field' : field };

                $.ajax({
                        url : 'GetAllLogs',
                        type : 'POST' , 
                        data : dataform , 
                        success : function(response) {
                            $('#displaylist').load('listgeneration.jsp');
                        },
                        error : function(){
                            alert("error");
                        }
                });
            }

            event.preventDefault();
    });

The servlet execution is an intence process and it takes some time.So i need to show a progress bar to the user regarding the execution status of servlet. More specifically i need it to be as.

@WebServlet("/GetAllLogs")
public class GetAllLogs extends HttpServlet
{
    public void doGet(HttpServletRequest request , HttpServletResponse response) throws ServletException , IOException  
    {
          PrintWriter obj = response.getWriter();
          obj.print(10);
          // at this point i need to set the progress bar value to 10%

          ....
          ....

          obj.print(40);
          // at this point i need to change the progress bar value to 40%
         .....
         .....

          obj.print(100);
           //at this point i neet to change the progress bar value to 100%
    }
}

basically i need to update the status bar for ever print value in the servlet.Is this approach possible and how can i do it. Thanks in advance

vignesh
  • 498
  • 8
  • 18

1 Answers1

3

Here are the basic steps:

  1. The first ajax call kicks off the long-running process and returns immediately.
  2. The long-running process is self aware of how long it will take and can report* how far along it is.
  3. Another endpoint provides the status of the long-running process. So another ajax call invoked every 1 second (or whatever is reasonable) to fetch the data to display in the progress bar.

*This could be something simple like an AtomicInteger stored in the session, and is updated as the long-running process does its work. However, the long-running process could be on some other JVM, or the endpoint providing the status could be on some other JVM. If this is the case, the initial call to kick off the long-running process should provide a unique token associated with the process. The long-running process updates some shared storage, such as a database, using the token as the key. The token is passed to the endpoint providing the status to look up the status.

edit to add additional context

ajax call to https://.../api/long/running/process/start

When this ajax call returns it invokes another method which starts polling the back-end. (Based on this other post.)

        $.ajax({
                    url : https://.../api/long/running/process/start,
                    type : 'POST' , 
                    data : dataform , 
                    success : function(response) {
                        pollForLongRunningStatus(response);
                    },
                    error : function(){
                        alert("error");
                    }
            });
        }

        pollForLongRunningStatus(response) {
           $.post('https://.../api/long/running/process/status', function(data) {
           alert(data);  // update the progress bar
           setTimeout(pollForLongRunningStatus, 1000);
          });
        }

Suppose the start URL is handled by the below class - it's important this class starts the long running process and returns immediately so it needs to run as an asnych task. (How to do that depends on the back-end framework, if any.)

@WebServlet("/.../api/long/running/process/start")
public class LongRunningProcessStartHandler extends HttpServlet  {
    public void doGet(HttpServletRequest request , HttpServletResponse response) throws ServletException , IOException  {

    AtomicInteger percentComplete = new AtomicInteger(0);
    request.getSession().setAttribute("LONG_RUNNING_PROCESS_STATUS", percentComplete);

    LongRunningProcess lrp = new LongRunningProcess(percentComplete);
    lrp.start();

}

public class LongRunningProcess extends Thread {
   private final AtomicInteger percentComplete;

   public LongRunningProcess(AtomicInteger percentComplete) {
       this.percentComplete = percentComplete;
   }

   public void run() {
       for (int i = 0; i < 100; i++) {
       Thread.sleep(1000);
       percentComplete.incrementAndGet();
   }
}

Meanwhile, the status URL just reports back the percent complete. Suppose this class handles the status endpoint:

@WebServlet("/.../api/long/running/process/status")
public class LongRunningProcessStatusHandler extends HttpServlet  {
    public void doGet(HttpServletRequest request , HttpServletResponse response) throws ServletException , IOException  {

    return request.getSession().getAttribute("LONG_RUNNING_PROCESS_STATUS").get();
}

That's the general idea. (Code above won't compile, and would need to be made null safe.) When the value reaches 100 then remove the object from the session to keep the session clean.

Andrew S
  • 2,509
  • 1
  • 12
  • 14
  • thanks for the response,i am a beginner and sorry i could get the whole concept.Could you please provide me any reference to start or some example code if you can – vignesh Mar 14 '18 at 16:11
  • could you please give me some more context on your third point – vignesh Mar 14 '18 at 16:15
  • I added more details. Hope this helps! – Andrew S Mar 14 '18 at 17:04
  • now i understand it and ill implement it.Thanks a lot for you help – vignesh Mar 14 '18 at 17:18
  • thank you very much it helped me a lot.I'm currently stuck with one problem.when trying to call the second servlet using post method i am getting a 404 error.how am i supposed to give the url path.I basically wrap all my class files into a jar and place it into WEB-INF/lib directory – vignesh Mar 15 '18 at 05:25
  • finally i was able to do it.Thank a lot for your help and time.Respect you guys keep spreading knowledge – vignesh Mar 15 '18 at 09:47
  • You might need to configure the web app to use the new class. Determine how the currently working class is configured. For example, make sure the new class is scanned. Check the log for details on the 404 error. – Andrew S Mar 15 '18 at 12:35