0

I want to solve following issue. I have a Spring-MVC Application with Thymeleaf, with a post request (sent by a form) I trigger a simulation task, what could take several minutes. The task process big number of data and we would like to have a progress bar via JavaScript. If there are two sessions, the simulation should be triggered independently and each browser shows its progress status.

Currently we have a solution, what is not really working well all the time.

The MVC Controller gets the Post request:

@Autowired SimulatorView view;  // SESSION SCOPE
@PostMapping("/view")
public String run(@ModelAttribute(CHECKS) ChecksDto checksWrapper, Model model) throws InterruptedException, ExecutionException {
    view.setStatisticDto(simulate(checksWrapper)); // Can take several minutes
    return "simulation/result :: simulated";
}

When I trigger the simulation on my WebGUI, a progress bar has been displayed and via JavaScript I am calling Rest Methods frequently to ask for the status of the progress.

RestController
@RequestMapping("simulation/api")
public class SimulatorApi {
    @Autowired SimulatorView view;  // SESSION SCOPE

    @RequestMapping("/progressStream")
    public double progressStream() {
        return view.getProgress().progressStream();
    }   

    @RequestMapping("/progressInvoice")
    public double progressInvoice() {
        return view.getProgress().progressInvoice();
    }
}

My JavaScript code snippet looks like:

function registerSimulationRunEvent() {
    // this is the id of the form
    $("#simulatorForm").submit(function(e) {
        handleSimulationStarted();

        var url = location.protocol + "//" + location.host + "/fdsclient/simulation/view";

        $.ajax({
            type: "POST",
            url: url,
            data: $("#simulatorForm").serialize(), // serializes the form's elements.
            success:    function(data) { handleSimulationFinished(); },
            error:      function(xhr, error) { handleSimulationError(); }
        });

        e.preventDefault(); // avoid to execute the actual submit of the form.
    });
}

function handleSimulationStarted() {
    replaceResultPanelRunning(); // THYMELEAF FRAGMENT EXCHANGE
}

function handleSimulationFinished() {
    stopResultPanelAnimation(); // STOP PROGRESS BAR ANIMATION
    replaceResultPanelSimulated(); // EXCHANGE THYMELEAF FRAGMENT
}

function handleSimulationError() {
    stopResultPanelAnimation();
    replaceResultPanelError();
}

function replaceResultPanelRunning() {
    var url = // URL;
    $("#resultDiv").load(url);
    startResultPanelAnimation();
}

// ANIMATION

var animationInterval = null;

function startResultPanelAnimation() {
    animationInterval = setInterval(animateResultPanel,4000);
}

function stopResultPanelAnimation() {
    clearInterval(animationInterval); // stop the interval
}

function animateResultPanel() {
    $("#simulatorProgressLabel").animate({opacity: '0.4'}, "slow");
    $("#simulatorProgressLabel").animate({opacity: '1.0'}, "slow");
}

I know using session scope for rest services is a bad thing, but I didn`t know yet what is a good and easy solution. On the other hand currently different browser can simulate independently, but not always the progress bar works (especially when trigger first time mostly doesnt work). The IE11 only works when the Developer Tools are activated. When deactivating the tool while progress, the progress bar stops to grow.

What I would like to know is, how a good solution looks like when using template engine with Spring-MVC and Thymeleaf for triggering the process and displaying the status of progress via Javascript (as JQUery). Thank you in advance.

Michael Hegner
  • 5,555
  • 9
  • 38
  • 64

2 Answers2

0

I have done a similar thing using Jquery AJAX POST submission. You can do something like this. This will submit POST request as a JSON format to the controller and wait for a response. A progress UI component can be shown during this waiting period.

              //Start Progress display
              function setStatistic(){

                    var data = JSON.stringify(//build your ChecksDto)
                    if (data) {
                        $.ajax({
                            url : '/view',
                            headers : {
                                'Content-Type' : 'application/json'
                            },
                            method : 'POST',
                            dataType : 'json',
                            data : data,
                            success : function(data) {
                                if (data.status == 200) {
                                    // Stop Progress display
                                    // Handle success status
                                } 
                            },

                            error : function(xhr, status, error) {
                                // Stop Progress display
                                // Handle errors here
                            }
                        });
                    }
                }

You also need to change Controller method to retrieve ajax requests as follows,

@ResponseBody
@PostMapping("/view")
public String run(@RequestBody ChecksDto checksWrapper, Model model) throws InterruptedException, ExecutionException
SAP
  • 468
  • 2
  • 14
  • Thank you for your reply, I edited my questions to make more clear. My Controller replace the thymeleaf fragment with the progress bar html snippet. On the fragment there are the progress bars controlled by JavaScript, which are frequently asking backend about status via ajax. The backend should give only the status of the SESSION object, it means if I have to sessions (two browser windows), they should work independently. On FireFox and Chrome it works mostly, but IE only when Developer Tools opened. My quesion is more how is a good way accessing Session Objects via Rest, if there is any. – Michael Hegner May 18 '17 at 07:53
0

At least I found the solution in another Stackoverflow Page. The magic word is setting ajax cache to false.

$.ajaxSetup ({
    // Disable caching of AJAX responses */
    cache: false
}); 
Michael Hegner
  • 5,555
  • 9
  • 38
  • 64